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:
56
400_xowa/src/gplx/xowa/addons/wikis/ctgs/Xoax_ctg_addon.java
Normal file
56
400_xowa/src/gplx/xowa/addons/wikis/ctgs/Xoax_ctg_addon.java
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
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.wikis.ctgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*;
|
||||
import gplx.xowa.wikis.data.tbls.*;
|
||||
public class Xoax_ctg_addon implements Xoax_addon_itm { // TODO_OLD: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 String Addon__key() {return ADDON_KEY;} private static final String ADDON_KEY = "xowa.apps.category";
|
||||
}
|
||||
32
400_xowa/src/gplx/xowa/addons/wikis/ctgs/Xoctg_ctg_itm.java
Normal file
32
400_xowa/src/gplx/xowa/addons/wikis/ctgs/Xoctg_ctg_itm.java
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
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.wikis.ctgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*;
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
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.wikis.htmls.css.bldrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.htmls.*; import gplx.xowa.addons.wikis.htmls.css.*;
|
||||
import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.wkrs.*; import gplx.xowa.wikis.*; import gplx.xowa.wikis.data.*;
|
||||
import gplx.xowa.addons.wikis.htmls.css.mgrs.*;
|
||||
public class Xob_css_cmd implements Xob_cmd {
|
||||
private final Xob_bldr bldr; private final Xowe_wiki wiki; private final Gfo_usr_dlg usr_dlg;
|
||||
private Io_url css_dir; private String css_key;
|
||||
public Xob_css_cmd(Xob_bldr bldr, Xowe_wiki wiki) {this.bldr = bldr; this.wiki = wiki; this.usr_dlg = wiki.Appe().Usr_dlg();}
|
||||
public String Cmd_key() {return Xob_cmd_keys.Key_text_css;}
|
||||
public Xob_cmd Cmd_clone(Xob_bldr bldr, Xowe_wiki wiki) {return null;}
|
||||
public void Cmd_init(Xob_bldr bldr) {
|
||||
if (css_dir == null) css_dir = wiki.App().Fsys_mgr().Wiki_css_dir(wiki.Domain_str()); // EX: /xowa/user/anonymous/wiki/en.wikipedia.org
|
||||
if (css_key == null) css_key = Xowd_css_core_mgr.Key_default;
|
||||
}
|
||||
public void Cmd_run() {
|
||||
usr_dlg.Plog_many("", "", Cmd_key() + ":bgn;");
|
||||
bldr.App().Html__css_installer().Install(wiki, null); // download from wmf
|
||||
usr_dlg.Plog_many("", "", Cmd_key() + ":css_dir; dir=~{0}", css_dir.Raw());
|
||||
wiki.Init_db_mgr(); // NOTE: must follow Install b/c Init_assert also calls Install; else will download any css from db
|
||||
Xow_db_file core_db = wiki.Db_mgr_as_sql().Core_data_mgr().Db__core();
|
||||
core_db.Conn().Txn_bgn("bldr__css");
|
||||
core_db.Tbl__css_core().Create_tbl();
|
||||
core_db.Tbl__css_file().Create_tbl();
|
||||
gplx.xowa.addons.wikis.htmls.css.mgrs.Xowd_css_core_mgr.Set(core_db.Tbl__css_core(), core_db.Tbl__css_file(), css_dir, css_key);
|
||||
core_db.Tbl__cfg().Upsert_yn(Xow_cfg_consts.Grp__wiki_schema, Xow_db_file_schema_props.Key__tbl_css_core, Bool_.Y);
|
||||
core_db.Conn().Txn_end();
|
||||
usr_dlg.Plog_many("", "", Cmd_key() + ":end;");
|
||||
}
|
||||
public void Cmd_bgn(Xob_bldr bldr) {}
|
||||
public void Cmd_end() {}
|
||||
public void Cmd_term() {}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_css_dir_)) css_dir = m.ReadIoUrl("v");
|
||||
else if (ctx.Match(k, Invk_css_key_)) css_key = m.ReadStr("v");
|
||||
else return Gfo_invk_.Rv_unhandled;
|
||||
return this;
|
||||
} private static final String Invk_css_dir_ = "css_dir_", Invk_css_key_ = "css_key_";
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
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.wikis.htmls.css.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.htmls.*; import gplx.xowa.addons.wikis.htmls.css.*;
|
||||
import gplx.dbs.*; import gplx.xowa.wikis.data.*;
|
||||
public class Css_db_mgr {
|
||||
private final Xow_wiki wiki;
|
||||
public Css_db_mgr(Xow_wiki wiki) {
|
||||
this.wiki = wiki;
|
||||
}
|
||||
public Db_conn Conn() {return conn;} private Db_conn conn;
|
||||
public Xowd_css_core_tbl Tbl__core() {return tbl__core;} private Xowd_css_core_tbl tbl__core;
|
||||
public Xowd_css_file_tbl Tbl__file() {return tbl__file;} private Xowd_css_file_tbl tbl__file;
|
||||
public Css_db_mgr Init() {
|
||||
this.conn = Get_or_new(wiki);
|
||||
this.tbl__core = new Xowd_css_core_tbl(conn);
|
||||
this.tbl__file = new Xowd_css_file_tbl(conn);
|
||||
if (!conn.Meta_tbl_exists(tbl__core.Tbl_name())) {
|
||||
tbl__core.Create_tbl();
|
||||
tbl__file.Create_tbl();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private static Db_conn Get_or_new(Xow_wiki wiki) {
|
||||
int layout_text = wiki.Data__core_mgr().Db__core().Db_props().Layout_text().Tid();
|
||||
Io_url url = null;
|
||||
switch (layout_text) {
|
||||
case Xow_db_layout.Tid__all: url = wiki.Data__core_mgr().Db__core().Url(); break;
|
||||
case Xow_db_layout.Tid__few: url = wiki.Fsys_mgr().Root_dir().GenSubFil(String_.Format("{0}-data.xowa", wiki.Domain_str())); break;
|
||||
case Xow_db_layout.Tid__lot: url = wiki.Fsys_mgr().Root_dir().GenSubFil(String_.Format("{0}-xtn.css.xowa", wiki.Domain_str())); break;
|
||||
default: throw Err_.new_unhandled(layout_text);
|
||||
}
|
||||
return Db_conn_bldr.Instance.Get_or_autocreate(true, url);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
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.wikis.htmls.css.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.htmls.*; import gplx.xowa.addons.wikis.htmls.css.*;
|
||||
public class Xowd_css_core_itm {
|
||||
public Xowd_css_core_itm(int id, String key, DateAdp updated_on) {
|
||||
this.id = id; this.key = key; this.updated_on = updated_on;
|
||||
}
|
||||
public int Id() {return id;} private final int id;
|
||||
public String Key() {return key;} private final String key;
|
||||
public DateAdp Updated_on() {return updated_on;} private final DateAdp updated_on;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.wikis.htmls.css.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.htmls.*; import gplx.xowa.addons.wikis.htmls.css.*;
|
||||
import gplx.dbs.*;
|
||||
public class Xowd_css_core_tbl implements Rls_able {
|
||||
private final Dbmeta_fld_list flds = new Dbmeta_fld_list();
|
||||
private final String fld_id, fld_key, fld_updated_on;
|
||||
public Xowd_css_core_tbl(Db_conn conn) {
|
||||
this.conn = conn;
|
||||
this.fld_id = flds.Add_int_pkey_autonum("css_id");
|
||||
this.fld_key = flds.Add_str("css_key", 255);
|
||||
this.fld_updated_on = flds.Add_str("css_updated_on", 20);
|
||||
conn.Rls_reg(this);
|
||||
}
|
||||
public Db_conn Conn() {return conn;} private final Db_conn conn;
|
||||
public String Tbl_name() {return tbl_name;} private final String tbl_name = "css_core";
|
||||
public void Create_tbl() {conn.Meta_tbl_create(Dbmeta_tbl_itm.New(tbl_name, flds, Dbmeta_idx_itm.new_unique_by_tbl(tbl_name, "main", fld_key)));}
|
||||
public void Rls() {}
|
||||
public int Insert(String key, DateAdp updated_on) {
|
||||
Db_stmt stmt_insert = conn.Stmt_insert(tbl_name, flds);
|
||||
stmt_insert.Val_str(fld_key, key).Val_str(fld_updated_on, updated_on.XtoStr_fmt_yyyyMMdd_HHmmss()).Exec_insert();
|
||||
return Select_id_by_key(key);
|
||||
}
|
||||
public void Update(int id, String key, DateAdp updated_on) {
|
||||
Db_stmt stmt_update = conn.Stmt_update_exclude(tbl_name, flds, fld_id);
|
||||
stmt_update.Val_str(fld_key, key).Val_str(fld_updated_on, updated_on.XtoStr_fmt_yyyyMMdd_HHmmss()).Crt_int(fld_id, id).Exec_update();
|
||||
}
|
||||
public Xowd_css_core_itm Select_by_key(String key) {
|
||||
Db_rdr rdr = conn.Stmt_select(tbl_name, flds, fld_key).Crt_str(fld_key, key).Exec_select__rls_auto();
|
||||
try {return rdr.Move_next() ? new_itm(rdr) : null;}
|
||||
finally {rdr.Rls();}
|
||||
}
|
||||
public int Select_id_by_key(String key) {
|
||||
Db_rdr rdr = conn.Stmt_select(tbl_name, flds, fld_key).Crt_str(fld_key, key).Exec_select__rls_auto();
|
||||
try {return rdr.Move_next() ? rdr.Read_int(fld_id) : Id_null;}
|
||||
finally {rdr.Rls();}
|
||||
}
|
||||
public Xowd_css_core_itm[] Select_all() { // TEST:
|
||||
Db_stmt stmt = conn.Stmt_select(tbl_name, flds);
|
||||
return Select_by_stmt(stmt);
|
||||
}
|
||||
private Xowd_css_core_itm[] Select_by_stmt(Db_stmt stmt) {
|
||||
List_adp rv = List_adp_.New();
|
||||
Db_rdr rdr = stmt.Exec_select__rls_auto();
|
||||
try {
|
||||
while (rdr.Move_next())
|
||||
rv.Add(new_itm(rdr));
|
||||
} finally {rdr.Rls();}
|
||||
return (Xowd_css_core_itm[])rv.To_ary_and_clear(Xowd_css_core_itm.class);
|
||||
}
|
||||
public void Delete_all() {
|
||||
conn.Stmt_delete(tbl_name).Exec_delete();
|
||||
}
|
||||
private Xowd_css_core_itm new_itm(Db_rdr rdr) {
|
||||
return new Xowd_css_core_itm(rdr.Read_int(fld_id), rdr.Read_str(fld_key), rdr.Read_date_by_str(fld_updated_on));
|
||||
}
|
||||
public static final int Id_null = -1;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
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.wikis.htmls.css.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.htmls.*; import gplx.xowa.addons.wikis.htmls.css.*;
|
||||
public class Xowd_css_file_itm {
|
||||
public Xowd_css_file_itm(int css_id, String path, byte[] data) {this.css_id = css_id; this.path = path; this.data = data;}
|
||||
public int Css_id() {return css_id;} private final int css_id;
|
||||
public String Path() {return path;} private final String path;
|
||||
public byte[] Data() {return data;} private final byte[] data;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
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.wikis.htmls.css.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.htmls.*; import gplx.xowa.addons.wikis.htmls.css.*;
|
||||
import gplx.dbs.*;
|
||||
public class Xowd_css_file_tbl implements Rls_able {
|
||||
private final String tbl_name = "css_file"; private final Dbmeta_fld_list flds = new Dbmeta_fld_list();
|
||||
private final String fld_css_id, fld_path, fld_data;
|
||||
private final Db_conn conn; private Db_stmt stmt_insert;
|
||||
public Xowd_css_file_tbl(Db_conn conn) {
|
||||
this.conn = conn;
|
||||
fld_css_id = flds.Add_int("css_id");
|
||||
fld_path = flds.Add_str("file_path", 255);
|
||||
fld_data = flds.Add_bry("file_data");
|
||||
conn.Rls_reg(this);
|
||||
}
|
||||
public void Rls() {
|
||||
stmt_insert = Db_stmt_.Rls(stmt_insert);
|
||||
}
|
||||
public void Create_tbl() {conn.Meta_tbl_create(Dbmeta_tbl_itm.New(tbl_name, flds));}
|
||||
public void Insert(int css_id, String path, byte[] data) {
|
||||
if (stmt_insert == null) stmt_insert = conn.Stmt_insert(tbl_name, flds);
|
||||
stmt_insert.Clear().Val_int(fld_css_id, css_id).Val_str(fld_path, path).Val_bry(fld_data, data).Exec_insert();
|
||||
}
|
||||
public void Delete(int css_id) {
|
||||
conn.Stmt_delete(tbl_name, fld_css_id).Crt_int(fld_css_id, css_id).Exec_delete();
|
||||
}
|
||||
public Xowd_css_file_itm[] Select_by_owner(int css_id) {
|
||||
Db_stmt stmt = conn.Stmt_select(tbl_name, flds, fld_css_id).Crt_int(fld_css_id, css_id);
|
||||
return Select_by_stmt(stmt);
|
||||
}
|
||||
public Xowd_css_file_itm[] Select_all() { // TEST:
|
||||
Db_stmt stmt = conn.Stmt_select(tbl_name, flds);
|
||||
return Select_by_stmt(stmt);
|
||||
}
|
||||
private Xowd_css_file_itm[] Select_by_stmt(Db_stmt stmt) {
|
||||
List_adp rv = List_adp_.New();
|
||||
Db_rdr rdr = stmt.Exec_select__rls_auto();
|
||||
try {
|
||||
while (rdr.Move_next())
|
||||
rv.Add(new_itm(rdr));
|
||||
} finally {rdr.Rls();}
|
||||
return (Xowd_css_file_itm[])rv.To_ary_and_clear(Xowd_css_file_itm.class);
|
||||
}
|
||||
public void Delete_all() {
|
||||
conn.Stmt_delete(tbl_name).Exec_delete();
|
||||
}
|
||||
private Xowd_css_file_itm new_itm(Db_rdr rdr) {return new Xowd_css_file_itm(rdr.Read_int(fld_css_id), rdr.Read_str(fld_path), rdr.Read_bry(fld_data));}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
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.wikis.htmls.css.mgrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.htmls.*; import gplx.xowa.addons.wikis.htmls.css.*;
|
||||
import gplx.xowa.wikis.*; import gplx.xowa.wikis.data.*;
|
||||
import gplx.xowa.bldrs.css.*;
|
||||
public class Xob_css_status {
|
||||
public int Update_tid() {return update_tid;} private int update_tid;
|
||||
public boolean Fs_exists() {return fs_exists;} private boolean fs_exists;
|
||||
public Io_url Fs_dir() {return fs_dir;} private Io_url fs_dir;
|
||||
public boolean Db_exists() {return db_exists;} private boolean db_exists;
|
||||
public void Fs_exists_(boolean fs_exists, Io_url fs_dir) {
|
||||
this.fs_exists = fs_exists;
|
||||
this.fs_dir = fs_dir;
|
||||
}
|
||||
public void Db_exists_(boolean db_exists) {
|
||||
this.db_exists = db_exists;
|
||||
}
|
||||
public void Update_tid_none_y_() {this.update_tid = Update_tid_none;}
|
||||
public void Update_tid_wmf_y_() {this.update_tid = Update_tid_wmf;}
|
||||
public void Update_tid_db_y_() {this.update_tid = Update_tid_db;}
|
||||
public static final int Update_tid_none = 0, Update_tid_db = 1, Update_tid_wmf = 2;
|
||||
public static Xob_css_status Chk(Xow_wiki wiki, Io_url css_dir, String key) {
|
||||
Xob_css_status rv = new Xob_css_status();
|
||||
Chk_fs(rv, wiki);
|
||||
Chk_db(rv, wiki, css_dir);
|
||||
return rv;
|
||||
}
|
||||
private static void Chk_fs(Xob_css_status rv, Xow_wiki wiki) {
|
||||
Io_url css_dir = wiki.App().Fsys_mgr().Wiki_css_dir(wiki.Domain_str()); // EX: /xowa/user/anonymous/wiki/en.wikipedia.org/html/
|
||||
Io_url css_fil_wiki = css_dir.GenSubFil(Xoa_css_extractor.Css_wiki_name); // EX: /xowa/user/anonymous/wiki/en.wikipedia.org/html/xowa_wiki.css
|
||||
boolean exists = Io_mgr.Instance.ExistsFil(css_fil_wiki);
|
||||
rv.Fs_exists_(exists, css_dir);
|
||||
}
|
||||
private static void Chk_db(Xob_css_status rv, Xow_wiki wiki, Io_url css_dir) {
|
||||
Xow_db_mgr core_db_mgr = wiki.Data__core_mgr();
|
||||
if ( core_db_mgr == null
|
||||
|| core_db_mgr.Props() != null
|
||||
|| !core_db_mgr.Props().Schema_is_1()
|
||||
|| core_db_mgr.Tbl__cfg().Select_yn_or(Xow_cfg_consts.Grp__wiki_schema, Xow_db_file_schema_props.Key__tbl_css_core, Bool_.N)
|
||||
) {
|
||||
rv.Db_exists_(false);
|
||||
if (rv.Fs_exists())
|
||||
rv.Update_tid_none_y_(); // v1_db and fs_exists; don't do update; legacy behavior
|
||||
else
|
||||
rv.Update_tid_wmf_y_(); // v1_db and fs_missing; update from wmf; legacy behavior
|
||||
}
|
||||
if (rv.Fs_exists()) {
|
||||
DateAdp fs_timestamp = Timestamp_load(css_dir);
|
||||
DateAdp db_timestamp = DateAdp_.Now();
|
||||
if (db_timestamp.compareTo(fs_timestamp) == CompareAble_.More)
|
||||
rv.Update_tid_db_y_(); // v2_db and later_version; update from db
|
||||
else
|
||||
rv.Update_tid_none_y_(); // v2_db and current version; noop
|
||||
}
|
||||
}
|
||||
public static void Timestamp_save(Io_url css_dir, DateAdp time) {
|
||||
Io_mgr.Instance.SaveFilStr(css_dir.GenSubFil(Timestamp_filename), time.XtoStr_fmt_yyyyMMdd_HHmmss());
|
||||
}
|
||||
public static DateAdp Timestamp_load(Io_url css_dir) {
|
||||
String rv = Io_mgr.Instance.LoadFilStr(css_dir.GenSubFil(Timestamp_filename));
|
||||
return rv == null ? DateAdp_.MinValue : DateAdp_.parse_iso8561_or(rv, DateAdp_.MinValue);
|
||||
}
|
||||
private static final String Timestamp_filename = "xowa.css.timestamp.txt";
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
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.wikis.htmls.css.mgrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.htmls.*; import gplx.xowa.addons.wikis.htmls.css.*;
|
||||
import gplx.xowa.wikis.*; import gplx.xowa.wikis.data.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
import gplx.xowa.addons.wikis.htmls.css.dbs.*;
|
||||
public class Xow_css_mgr {
|
||||
private final Xow_wiki wiki;
|
||||
private boolean db_css_exists;
|
||||
private Xowd_css_core_tbl css_core_tbl; private Xowd_css_file_tbl css_file_tbl;
|
||||
public Xow_css_mgr(Xow_wiki wiki) {this.wiki = wiki;}
|
||||
public void Init_by_wiki() {
|
||||
Gfo_usr_dlg usr_dlg = Xoa_app_.Usr_dlg();
|
||||
Xow_db_mgr core_db_mgr = wiki.Data__core_mgr();
|
||||
if (core_db_mgr == null) {
|
||||
usr_dlg.Log_many("", "", "db.css.exists; css_missing b/c tdb; wiki=~{0}", wiki.Domain_str());
|
||||
return;
|
||||
}
|
||||
if ( core_db_mgr.Props() == null
|
||||
|| core_db_mgr.Props().Schema_is_1()) {
|
||||
usr_dlg.Log_many("", "", "db.css.exists; css_missing b/c v1; wiki=~{0}", wiki.Domain_str());
|
||||
return;
|
||||
}
|
||||
Xow_db_file core_db = core_db_mgr.Db__core();
|
||||
this.css_core_tbl = core_db.Tbl__css_core();
|
||||
this.css_file_tbl = core_db.Tbl__css_file();
|
||||
if ( core_db == null
|
||||
|| !core_db.Conn().Meta_tbl_exists(css_core_tbl.Tbl_name())
|
||||
) {
|
||||
usr_dlg.Log_many("", "", "db.css.exists; css_missing b/c v2 w/o css; wiki=~{0}", wiki.Domain_str());
|
||||
return;
|
||||
}
|
||||
this.db_css_exists = true;
|
||||
}
|
||||
public void Db_del_all() {
|
||||
if (!db_css_exists) {Xoa_app_.Usr_dlg().Log_many("", "", "db.css.del_all; del_all skipped; wiki=~{0}", wiki.Domain_str()); return;}
|
||||
css_core_tbl.Delete_all();
|
||||
css_file_tbl.Delete_all();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
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.wikis.htmls.css.mgrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.htmls.*; import gplx.xowa.addons.wikis.htmls.css.*;
|
||||
import gplx.core.envs.*;
|
||||
import gplx.dbs.*;
|
||||
import gplx.xowa.wikis.*; import gplx.xowa.wikis.data.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
import gplx.xowa.addons.wikis.htmls.css.dbs.*;
|
||||
public class Xowd_css_core_mgr {
|
||||
public static void Set(Xowd_css_core_tbl core_tbl, Xowd_css_file_tbl file_tbl, Io_url css_dir, String key) {
|
||||
Db_conn conn = core_tbl.Conn();
|
||||
Io_url[] file_list = Io_mgr.Instance.QueryDir_args(css_dir).Recur_().ExecAsUrlAry();
|
||||
try {
|
||||
conn.Txn_bgn("schema__css_core__set");
|
||||
int css_id = core_tbl.Select_id_by_key(key);
|
||||
DateAdp updated_on = DateAdp_.Now().XtoUtc();
|
||||
if (css_id == -1)
|
||||
css_id = core_tbl.Insert(key, updated_on);
|
||||
else {
|
||||
core_tbl.Update(css_id, key, updated_on);
|
||||
file_tbl.Delete(css_id);
|
||||
}
|
||||
for (Io_url file : file_list) {
|
||||
String path = Op_sys.Fsys_path_to_lnx(file.GenRelUrl_orEmpty(css_dir));
|
||||
byte[] data = Io_mgr.Instance.LoadFilBry(file);
|
||||
file_tbl.Insert(css_id, path, data);
|
||||
}
|
||||
conn.Txn_end();
|
||||
}
|
||||
catch (Exception e) {conn.Txn_cxl(); throw e;}
|
||||
}
|
||||
public static boolean Get(Xowd_css_core_tbl core_tbl, Xowd_css_file_tbl file_tbl, Io_url css_dir, String key) {
|
||||
String dbg = "enter";
|
||||
try {
|
||||
int css_id = core_tbl.Select_id_by_key(key);
|
||||
dbg += ";css_id";
|
||||
if (css_id == Xowd_css_core_tbl.Id_null) return false; // unknown key; return false (not found)
|
||||
dbg += ";select_by_owner";
|
||||
Xowd_css_file_itm[] file_list = file_tbl.Select_by_owner(css_id);
|
||||
dbg += ";file_list:" + file_list.length;
|
||||
// Io_mgr.Instance.DeleteDirDeep(css_dir); // NOTE: do not delete existing files; just overwrite;
|
||||
int len = file_list.length;
|
||||
if (len == 0) return false; // no css files in db
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Xowd_css_file_itm file = file_list[i];
|
||||
dbg += ";file_url:" + file.Path();
|
||||
Io_url file_url = Io_url_.new_fil_(css_dir.Gen_sub_path_for_os(file.Path()));
|
||||
if (file.Data() == null) continue; // NOTE: sqlite will return 0 length fields as NULL; if no data, just ignore, else error below
|
||||
Io_mgr.Instance.SaveFilBry(file_url, file.Data());
|
||||
dbg += ";file_data:" + file.Data().length;
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {throw Err_.new_exc(e, "css", "Xowd_css_core_mgr.Get failed", "dbg", dbg, "err", Err_.Message_gplx_log(e));}
|
||||
}
|
||||
public static final String Key_default = "xowa.default", Key_mobile = "xowa.mobile";
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
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.wikis.htmls.css.mgrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.htmls.*; import gplx.xowa.addons.wikis.htmls.css.*;
|
||||
import org.junit.*; import gplx.core.ios.*; import gplx.dbs.*; import gplx.xowa.wikis.data.tbls.*; import gplx.xowa.addons.wikis.htmls.css.dbs.*;
|
||||
public class Xowd_css_core_mgr_tst {
|
||||
@Before public void init() {fxt.Clear();} private Xowd_css_core_mgr_fxt fxt = new Xowd_css_core_mgr_fxt();
|
||||
@Test public void Basic() {
|
||||
Xowd_css_core_itm[] skin_ary = fxt.Make_skin_ary
|
||||
( fxt.Make_skin_itm(1, "desktop", "20010101_050200")
|
||||
);
|
||||
Xowd_css_file_itm[] file_ary = fxt.Make_file_ary
|
||||
( fxt.Make_file_itm(1, "a.css", "a_data")
|
||||
, fxt.Make_file_itm(1, "b/b.png", "b/b_data")
|
||||
);
|
||||
Io_url src_dir = Io_url_.mem_dir_("mem/src/");
|
||||
fxt.Init_fs(src_dir, file_ary);
|
||||
fxt.Exec_set(src_dir, "desktop");
|
||||
fxt.Test_skin_tbl(skin_ary);
|
||||
fxt.Test_file_tbl(file_ary);
|
||||
|
||||
Io_url trg_dir = Io_url_.mem_dir_("mem/trg/");
|
||||
fxt.Exec_get(trg_dir, "desktop");
|
||||
fxt.Test_fs(trg_dir, file_ary);
|
||||
}
|
||||
@Test public void Update() { // update css files; keep same skin_id; insert new files
|
||||
Xowd_css_core_itm[] skin_ary = fxt.Make_skin_ary
|
||||
( fxt.Make_skin_itm(1, "desktop", "20010101_050500")
|
||||
);
|
||||
Xowd_css_file_itm[] file_ary = fxt.Make_file_ary
|
||||
( fxt.Make_file_itm(1, "a.css", "a_data")
|
||||
, fxt.Make_file_itm(1, "b/b.png", "b/b_data")
|
||||
);
|
||||
Io_url src_dir = Io_url_.mem_dir_("mem/src/");
|
||||
fxt.Init_fs(src_dir, file_ary);
|
||||
fxt.Exec_set(src_dir, "desktop");
|
||||
|
||||
file_ary = fxt.Make_file_ary
|
||||
( fxt.Make_file_itm(1, "a1.css", "a1_data")
|
||||
, fxt.Make_file_itm(1, "b/b1.png", "b/b1_data")
|
||||
);
|
||||
Io_mgr.Instance.DeleteDirDeep(src_dir);
|
||||
fxt.Init_fs(src_dir, file_ary);
|
||||
fxt.Exec_set(src_dir, "desktop");
|
||||
fxt.Test_skin_tbl(skin_ary);
|
||||
fxt.Test_file_tbl(file_ary);
|
||||
}
|
||||
}
|
||||
class Xowd_css_core_mgr_fxt {
|
||||
private final Bry_bfr bfr = Bry_bfr_.Reset(32);
|
||||
private Xowd_css_core_tbl core_tbl; private Xowd_css_file_tbl file_tbl;
|
||||
public void Clear() {
|
||||
Tfds.Now_enabled_y_();
|
||||
Io_mgr.Instance.InitEngine_mem();
|
||||
Db_conn_bldr.Instance.Reg_default_mem();
|
||||
Db_conn conn = Db_conn_bldr.Instance.New(Io_url_.mem_fil_("mem/db/css.sqlite3"));
|
||||
this.core_tbl = new Xowd_css_core_tbl(conn);
|
||||
this.file_tbl = new Xowd_css_file_tbl(conn);
|
||||
core_tbl.Create_tbl();
|
||||
file_tbl.Create_tbl();
|
||||
}
|
||||
public Xowd_css_core_itm Make_skin_itm(int id, String key, String updated_on) {return new Xowd_css_core_itm(id, key, DateAdp_.parse_gplx(updated_on));}
|
||||
public Xowd_css_file_itm Make_file_itm(int skin_id, String path, String data) {return new Xowd_css_file_itm(skin_id, path, Bry_.new_u8(data));}
|
||||
public Xowd_css_file_itm[] Make_file_ary(Xowd_css_file_itm... ary) {return ary;}
|
||||
public Xowd_css_core_itm[] Make_skin_ary(Xowd_css_core_itm... ary) {return ary;}
|
||||
public void Init_fs(Io_url css_dir, Xowd_css_file_itm[] file_ary) {
|
||||
for (Xowd_css_file_itm itm : file_ary)
|
||||
Io_mgr.Instance.SaveFilBry(css_dir.GenSubFil(itm.Path()), itm.Data());
|
||||
}
|
||||
public void Exec_set(Io_url css_dir, String key) {Xowd_css_core_mgr.Set(core_tbl, file_tbl, css_dir, key);}
|
||||
public void Exec_get(Io_url css_dir, String key) {Xowd_css_core_mgr.Get(core_tbl, file_tbl, css_dir, key);}
|
||||
public void Test_skin_tbl(Xowd_css_core_itm[] expd) {
|
||||
Xowd_css_core_itm[] actl = core_tbl.Select_all();
|
||||
Tfds.Eq_str_lines(To_str(expd), To_str(actl));
|
||||
}
|
||||
public void Test_file_tbl(Xowd_css_file_itm[] expd) {
|
||||
Xowd_css_file_itm[] actl = file_tbl.Select_all();
|
||||
Tfds.Eq_str_lines(To_str(expd), To_str(actl));
|
||||
}
|
||||
public void Test_fs(Io_url css_dir, Xowd_css_file_itm[] expd) {
|
||||
Io_url[] actl = Io_mgr.Instance.QueryDir_args(css_dir).Recur_().ExecAsUrlAry();
|
||||
int len = expd.length;
|
||||
Tfds.Eq(len, actl.length);
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Xowd_css_file_itm expd_itm = expd[i];
|
||||
Tfds.Eq_bry(expd_itm.Data(), Io_mgr.Instance.LoadFilBry(actl[i]));
|
||||
}
|
||||
}
|
||||
private String To_str(Xowd_css_file_itm[] ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Xowd_css_file_itm itm = ary[i];
|
||||
bfr.Add_int_variable(itm.Css_id()).Add_byte_pipe().Add_str_u8(itm.Path()).Add_byte_pipe().Add(itm.Data()).Add_byte_nl();
|
||||
}
|
||||
return bfr.To_str_and_clear();
|
||||
}
|
||||
private String To_str(Xowd_css_core_itm[] ary) {
|
||||
Bry_bfr bfr = Bry_bfr_.New();
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Xowd_css_core_itm itm = ary[i];
|
||||
bfr.Add_int_variable(itm.Id()).Add_byte_pipe().Add_str_u8(itm.Key()).Add_byte_pipe().Add_str_u8(itm.Updated_on().XtoStr_fmt_yyyyMMdd_HHmmss()).Add_byte_nl();
|
||||
}
|
||||
return bfr.To_str_and_clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
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.wikis.imports; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*;
|
||||
import gplx.xowa.specials.*;
|
||||
public class Xow_import_addon implements Xoax_addon_itm, Xoax_addon_itm__special {
|
||||
public Xow_special_page[] Special_pages() {
|
||||
return new Xow_special_page[]
|
||||
{ Xow_import_special.Prototype
|
||||
};
|
||||
}
|
||||
|
||||
public String Addon__key() {return "xowa.apps.file_browsers";}
|
||||
}
|
||||
@@ -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.wikis.imports; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*;
|
||||
import gplx.core.ios.*;
|
||||
import gplx.langs.mustaches.*;
|
||||
class Xow_import_doc 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 Xow_import_doc[] subs;
|
||||
public Xow_import_doc(boolean is_dir, boolean is_core_xowa, int color, byte[] owner_dir, byte[] path, byte[] name, byte[] date, byte[] size, Xow_import_doc[] 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 Xow_import_doc[] Ary_empty = new Xow_import_doc[0];
|
||||
public static Xow_import_doc 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());
|
||||
Xow_import_doc[] subs = (Xow_import_doc[])sub_list.To_ary_and_clear(Xow_import_doc.class);
|
||||
return new Xow_import_doc(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);
|
||||
Xow_import_doc trg = null;
|
||||
if (src.Type_dir()) {
|
||||
byte[] trg_url = src.Url().RawBry();
|
||||
trg = new Xow_import_doc(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.Xow_db_file__core_.Is_core_fil_name(owner_dir.NameOnly(), src.Url().NameAndExt());
|
||||
trg = new Xow_import_doc(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
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.wikis.imports; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*;
|
||||
import gplx.xowa.specials.*; import gplx.langs.mustaches.*; import gplx.xowa.wikis.pages.*; import gplx.xowa.wikis.pages.tags.*;
|
||||
import gplx.core.ios.*;
|
||||
class Xow_import_html extends Xow_special_wtr__base {
|
||||
private final Io_url owner_url;
|
||||
public Xow_import_html(Io_url owner_url) {this.owner_url = owner_url;}
|
||||
@Override protected Io_url Get_addon_dir(Xoa_app app) {return app.Fsys_mgr().Http_root().GenSubDir_nest("bin", "any", "xowa", "addon", "wiki", "import");}
|
||||
@Override protected Io_url Get_mustache_fil(Io_url addon_dir) {return addon_dir.GenSubFil_nest("bin", "xow_import.mustache.html");}
|
||||
@Override protected Mustache_doc_itm Bld_mustache_root(Xoa_app app) {
|
||||
IoItmDir owner_dir = Io_mgr.Instance.QueryDir_args(owner_url).DirInclude_(true).ExecAsDir();
|
||||
return Xow_import_doc.New(owner_dir);
|
||||
}
|
||||
@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());
|
||||
head_tags.Add(Xopg_tag_itm.New_css_file(addon_dir.GenSubFil_nest("bin", "xow_import.css")));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
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.wikis.imports; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*;
|
||||
import gplx.xowa.specials.*; import gplx.core.net.*; import gplx.core.net.qargs.*; import gplx.xowa.wikis.pages.*;
|
||||
import gplx.core.ios.*;
|
||||
public class Xow_import_special implements Xow_special_page {
|
||||
public void Special__gen(Xow_wiki wiki, Xoa_page page, Xoa_url url, Xoa_ttl ttl) {
|
||||
Gfo_qarg_mgr url_args = new Gfo_qarg_mgr().Init(url.Qargs_ary());
|
||||
|
||||
// get path
|
||||
String owner_str = url_args.Read_str_or_null("path");
|
||||
if (owner_str == null) {
|
||||
Xopage_html_data.err_("url has unknown path").Apply(page);
|
||||
return;
|
||||
}
|
||||
|
||||
new Xow_import_html(Io_url_.new_dir_(owner_str)).Bld_page_by_mustache(wiki.App(), page, this);
|
||||
}
|
||||
|
||||
Xow_import_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 Xow_import_special(Xow_special_meta.New_xo("XowaWikiImport", "Import wiki", "XowaFileBrowser"));
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
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.wikis.pages.randoms; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*;
|
||||
import gplx.xowa.bldrs.wkrs.*; import gplx.xowa.addons.wikis.pages.randoms.bldrs.*;
|
||||
import gplx.xowa.specials.*; import gplx.xowa.addons.wikis.pages.randoms.specials.*;
|
||||
import gplx.xowa.addons.wikis.pages.randoms.mgrs.*;
|
||||
public class Rndm_addon implements Xoax_addon_itm, Xoax_addon_itm__bldr, Xoax_addon_itm__special {
|
||||
public Rndm_addon() {this.mgr = null;} // prototype
|
||||
public Rndm_addon(Xow_wiki wiki) {this.mgr = new Rndm_mgr(wiki);}
|
||||
public Rndm_mgr Mgr() {return mgr;} private final Rndm_mgr mgr;
|
||||
public Xob_cmd[] Bldr_cmds() {
|
||||
return new Xob_cmd[]
|
||||
{ Rndm_bldr_cmd.Prototype
|
||||
};
|
||||
}
|
||||
public Xow_special_page[] Special_pages() {
|
||||
return new Xow_special_page[]
|
||||
{ Rndm_root_special.Prototype
|
||||
, Rndm_page_special.Prototype
|
||||
};
|
||||
}
|
||||
|
||||
public static Rndm_addon Get(Xow_wiki wiki) {
|
||||
Rndm_addon rv = (Rndm_addon)wiki.Addon_mgr().Itms__get_or_null(ADDON_KEY);
|
||||
if (rv == null) {
|
||||
rv = new Rndm_addon(wiki);
|
||||
wiki.Addon_mgr().Itms__add(rv);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
public String Addon__key() {return ADDON_KEY;} private static final String ADDON_KEY = "xowa.builds.randoms";
|
||||
|
||||
}
|
||||
@@ -15,22 +15,20 @@ 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.wikis.randoms.bldrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.randoms.*;
|
||||
package gplx.xowa.addons.wikis.pages.randoms.bldrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.randoms.*;
|
||||
import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.wkrs.*;
|
||||
public class Rndm_bldr_cmd extends Xob_cmd__base {
|
||||
private int rndm_uid = 0; private String rndm_where_sql = "AND ~{page_namespace} = 0 AND ~{page_is_redirect} = 0"; private int rndm_interval = 1000;
|
||||
private int rndm_interval = 1000;
|
||||
public Rndm_bldr_cmd(Xob_bldr bldr, Xowe_wiki wiki) {super(bldr, wiki);}
|
||||
@Override public void Cmd_run() {
|
||||
// wiki.Special_mgr().Page_random().Mgr().Rebuild(rndm_uid, rndm_where_sql, rndm_interval);
|
||||
Tfds.Write(rndm_uid, rndm_where_sql, rndm_interval);
|
||||
wiki.Init_assert();
|
||||
new Rndm_ns_rebuilder().Exec(wiki, rndm_interval);
|
||||
}
|
||||
@Override public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_rndm_uid_)) rndm_uid = m.ReadInt("v");
|
||||
else if (ctx.Match(k, Invk_rndm_where_sql_)) rndm_where_sql = m.ReadStr("v");
|
||||
else if (ctx.Match(k, Invk_rndm_interval_)) rndm_interval = m.ReadInt("v");
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
if (ctx.Match(k, Invk_rndm_interval_)) rndm_interval = m.ReadInt("v");
|
||||
else return Gfo_invk_.Rv_unhandled;
|
||||
return this;
|
||||
} private static final String Invk_rndm_uid_ = "rndm_uid_", Invk_rndm_where_sql_ = "rndm_where_sql_", Invk_rndm_interval_ = "rndm_interval_";
|
||||
} private static final String Invk_rndm_interval_ = "rndm_interval_";
|
||||
|
||||
public static final String BLDR_CMD_KEY = "wiki.random";
|
||||
@Override public String Cmd_key() {return BLDR_CMD_KEY;}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
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.wikis.pages.randoms.bldrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.randoms.*;
|
||||
import gplx.dbs.*; import gplx.xowa.addons.wikis.pages.randoms.dbs.*;
|
||||
public class Rndm_bldr_wkr {
|
||||
private final Rndm_qry_tbl qry_tbl; private final Rndm_rng_tbl rng_tbl; private final Rndm_seq_tbl seq_tbl;
|
||||
private Rndm_qry_itm qry_itm;
|
||||
private Db_stmt rng_stmt, seq_stmt;
|
||||
private int rng_seq_bgn, seq_in_rng;
|
||||
private int qry_idx_max = 0;
|
||||
public Rndm_bldr_wkr(Db_conn conn, Rndm_qry_tbl qry_tbl, Rndm_rng_tbl rng_tbl, Rndm_seq_tbl seq_tbl) {
|
||||
this.conn = conn;
|
||||
this.qry_tbl = qry_tbl; this.rng_tbl = rng_tbl; this.seq_tbl = seq_tbl;
|
||||
qry_idx_max = qry_tbl.Select_qry_max();
|
||||
}
|
||||
public Db_conn Conn() {return conn;} private final Db_conn conn;
|
||||
public int Qry_idx() {return qry_idx;} private int qry_idx;
|
||||
public int Rng_idx() {return rng_idx;} private int rng_idx;
|
||||
public int Seq_in_qry() {return seq_in_qry;} private int seq_in_qry;
|
||||
public void Exec_qry_bgn(Rndm_qry_itm qry_itm) {
|
||||
this.qry_itm = qry_itm;
|
||||
|
||||
qry_idx = qry_tbl.Select_by_key(qry_itm.Qry_key());
|
||||
if (qry_idx == -1)
|
||||
qry_idx = ++qry_idx_max;
|
||||
else {
|
||||
// delete all
|
||||
qry_tbl.Delete_by_qry_idx(qry_idx);
|
||||
rng_tbl.Delete_by_qry_idx(qry_idx);
|
||||
seq_tbl.Delete_by_qry_idx(qry_idx);
|
||||
}
|
||||
|
||||
rng_idx = seq_in_rng = seq_in_qry = 0;
|
||||
rng_stmt = rng_tbl.Insert_stmt();
|
||||
seq_stmt = seq_tbl.Insert_stmt();
|
||||
}
|
||||
public void Exec_qry_end() {
|
||||
if (seq_in_qry == 0) return; // no sequences added
|
||||
qry_tbl.Insert(qry_idx, rng_idx, qry_itm.Qry_key(), qry_itm.Qry_data(), qry_itm.Qry_name());
|
||||
}
|
||||
public void Exec_rng_bgn() {
|
||||
rng_seq_bgn = seq_in_qry;
|
||||
++rng_idx;
|
||||
seq_in_rng = 0;
|
||||
}
|
||||
public Rndm_rng_itm Exec_rng_end_or_null() {
|
||||
if (seq_in_rng == 0) return null; // no sequences added; return null;
|
||||
Rndm_rng_itm rv = new Rndm_rng_itm(qry_idx, rng_idx, rng_seq_bgn, seq_in_qry);
|
||||
rng_tbl.Insert(rng_stmt, qry_idx, rng_idx, rng_seq_bgn, seq_in_qry);
|
||||
return rv;
|
||||
}
|
||||
public void Exec_seq_itm(int page_id) {
|
||||
seq_tbl.Insert(seq_stmt, qry_idx, rng_idx, seq_in_rng, page_id);
|
||||
++seq_in_qry;
|
||||
++seq_in_rng;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
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.wikis.pages.randoms.bldrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.randoms.*;
|
||||
import gplx.dbs.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
import gplx.xowa.wikis.nss.*;
|
||||
import gplx.xowa.addons.wikis.pages.randoms.dbs.*;
|
||||
class Rndm_ns_rebuilder {
|
||||
public void Exec(Xow_wiki wiki, int rndm_interval) {
|
||||
// get wkr; page_tbl
|
||||
Rndm_addon addon = Rndm_addon.Get(wiki);
|
||||
Rndm_bldr_wkr wkr = addon.Mgr().New_bldr();
|
||||
Xowd_page_tbl page_tbl = wiki.Data__core_mgr().Db__core().Tbl__page();
|
||||
String fld_page_id = page_tbl.Fld_page_id();
|
||||
Db_conn page_conn = page_tbl.Conn();
|
||||
page_conn.Meta_idx_assert(page_tbl.Tbl_name(), "rndm_rebuild", page_tbl.Fld_page_ns(), fld_page_id);
|
||||
|
||||
// loop over ns
|
||||
Xow_ns_mgr ns_mgr = wiki.Ns_mgr();
|
||||
int len = ns_mgr.Ids_len();
|
||||
wkr.Conn().Txn_bgn("rndm");
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Xow_ns ns = ns_mgr.Ids_get_at(i);
|
||||
Gfo_log_.Instance.Prog("reading ns", "ns", ns.Id());
|
||||
int page_id_cur = -1;
|
||||
wkr.Exec_qry_bgn(Rndm_qry_itm.New_by_ns(wiki, ns.Id()));
|
||||
|
||||
// read pages in ns where page_id > last_page_id
|
||||
while (true) {
|
||||
Gfo_log_.Instance.Prog("reading pages", "page_id", page_id_cur);
|
||||
String sql = String_.Format("SELECT * FROM page WHERE page_namespace = {0} AND page_id > {1} ORDER BY page_id", ns.Id(), page_id_cur); // ANSI.Y
|
||||
int rdr_count = 0;
|
||||
wkr.Exec_rng_bgn();
|
||||
Db_rdr rdr = page_conn.Stmt_sql(sql).Exec_select__rls_auto();
|
||||
try {
|
||||
// read pages until rndm_interval
|
||||
while (rdr.Move_next()) {
|
||||
int page_id = rdr.Read_int(fld_page_id);
|
||||
wkr.Exec_seq_itm(page_id);
|
||||
if (++rdr_count == rndm_interval) {
|
||||
page_id_cur = page_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {rdr.Rls();}
|
||||
wkr.Exec_rng_end_or_null();
|
||||
if (rdr_count != rndm_interval)
|
||||
break;
|
||||
}
|
||||
wkr.Exec_qry_end();
|
||||
}
|
||||
wkr.Conn().Txn_end();
|
||||
page_conn.Meta_idx_delete("page", "rndm_rebuild");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
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.wikis.pages.randoms.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.randoms.*;
|
||||
import gplx.dbs.*;
|
||||
import gplx.xowa.wikis.data.*;
|
||||
public class Rndm_db_mgr {
|
||||
private final Xow_wiki wiki;
|
||||
public Rndm_db_mgr(Xow_wiki wiki) {
|
||||
this.wiki = wiki;
|
||||
}
|
||||
public Db_conn Conn() {return conn;} private Db_conn conn;
|
||||
public Rndm_qry_tbl Tbl__qry() {return tbl__qry;} private Rndm_qry_tbl tbl__qry;
|
||||
public Rndm_rng_tbl Tbl__rng() {return tbl__rng;} private Rndm_rng_tbl tbl__rng;
|
||||
public Rndm_seq_tbl Tbl__seq() {return tbl__seq;} private Rndm_seq_tbl tbl__seq;
|
||||
public Rndm_db_mgr Init() {
|
||||
this.conn = Get_or_new(wiki);
|
||||
this.tbl__qry = new Rndm_qry_tbl(conn);
|
||||
this.tbl__rng = new Rndm_rng_tbl(conn);
|
||||
this.tbl__seq = new Rndm_seq_tbl(conn);
|
||||
if (!conn.Meta_tbl_exists(tbl__qry.Tbl_name())) {
|
||||
tbl__qry.Create_tbl();
|
||||
tbl__rng.Create_tbl();
|
||||
tbl__seq.Create_tbl();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private static Db_conn Get_or_new(Xow_wiki wiki) {
|
||||
int layout_text = wiki.Data__core_mgr().Db__core().Db_props().Layout_text().Tid();
|
||||
Io_url url = null;
|
||||
switch (layout_text) {
|
||||
case Xow_db_layout.Tid__all: url = wiki.Data__core_mgr().Db__core().Url(); break;
|
||||
case Xow_db_layout.Tid__few: url = wiki.Fsys_mgr().Root_dir().GenSubFil(String_.Format("{0}-data.xowa", wiki.Domain_str())); break;
|
||||
case Xow_db_layout.Tid__lot: url = wiki.Fsys_mgr().Root_dir().GenSubFil(String_.Format("{0}-xtn.random.core.xowa", wiki.Domain_str())); break;
|
||||
default: throw Err_.new_unhandled(layout_text);
|
||||
}
|
||||
return Db_conn_bldr.Instance.Get_or_autocreate(true, url);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
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.wikis.pages.randoms.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.randoms.*;
|
||||
public class Rndm_qry_itm {
|
||||
public Rndm_qry_itm(int qry_idx, int rng_end, String qry_key, String qry_data, String qry_name) {
|
||||
this.qry_idx = qry_idx;
|
||||
this.rng_end = rng_end;
|
||||
this.qry_key = qry_key;
|
||||
this.qry_data = qry_data;
|
||||
this.qry_name = qry_name;
|
||||
}
|
||||
public int Qry_idx() {return qry_idx;} private final int qry_idx;
|
||||
public int Rng_end() {return rng_end;} private final int rng_end;
|
||||
public String Qry_key() {return qry_key;} private final String qry_key;
|
||||
public String Qry_data() {return qry_data;} private final String qry_data;
|
||||
public String Qry_name() {return qry_name;} private final String qry_name;
|
||||
public int Seq_max() {return seq_max;} private int seq_max; public void Seq_max_(int v) {this.seq_max = v;}
|
||||
|
||||
public static Rndm_qry_itm New_by_ns(Xow_wiki wiki, int ns_id) {
|
||||
String ns_str = Int_.To_str(ns_id);
|
||||
String qry_key = "xowa.ns." + ns_str; // xowa.ns.0
|
||||
String qry_data = "type=ns;ns=" + ns_str; // type=ns;ns=0
|
||||
String qry_name = "Namespace " + ns_str + " - All";
|
||||
return new Rndm_qry_itm(-1, -1, qry_key, qry_data, qry_name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
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.wikis.pages.randoms.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.randoms.*;
|
||||
import gplx.core.ios.*; import gplx.dbs.*; import gplx.dbs.utls.*;
|
||||
public class Rndm_qry_tbl implements Rls_able {
|
||||
private final String tbl_name = "rndm_qry"; private final Dbmeta_fld_list flds = new Dbmeta_fld_list();
|
||||
private final String fld_qry_idx, fld_rng_end, fld_qry_key, fld_qry_data, fld_qry_name;
|
||||
private final Db_conn conn;
|
||||
public Rndm_qry_tbl(Db_conn conn) {
|
||||
this.conn = conn;
|
||||
fld_qry_idx = flds.Add_int_pkey("qry_idx"); // EX: 0
|
||||
fld_rng_end = flds.Add_int("rng_end"); // EX: 123
|
||||
fld_qry_key = flds.Add_str("qry_key", 255); // EX: xowa.ns.0
|
||||
fld_qry_data = flds.Add_str("qry_data", 255); // EX: type=ns;ns=0
|
||||
fld_qry_name = flds.Add_str("qry_name", 255); // EX: Main Namespace - All
|
||||
conn.Rls_reg(this);
|
||||
}
|
||||
public String Tbl_name() {return tbl_name;}
|
||||
public void Create_tbl() {conn.Meta_tbl_create(Dbmeta_tbl_itm.New(tbl_name, flds));}
|
||||
public int Select_rng_end(int qry_idx) {
|
||||
Db_rdr rdr = conn.Stmt_select(tbl_name, flds, fld_qry_idx).Exec_select__rls_auto();
|
||||
try {return rdr.Move_next() ? rdr.Read_int(fld_rng_end) : 0;}
|
||||
finally {rdr.Rls();}
|
||||
}
|
||||
public int Select_qry_max() {
|
||||
Db_rdr rdr = conn.Stmt_sql("SELECT Coalesce(Max(qry_idx), 0) AS qry_idx FROM rndm_qry").Exec_select__rls_auto(); // ANSI.Y
|
||||
try {return rdr.Move_next() ? rdr.Read_int(fld_qry_idx) : 0;}
|
||||
finally {rdr.Rls();}
|
||||
}
|
||||
public int Select_by_key(String key) {
|
||||
Db_rdr rdr = conn.Stmt_select(tbl_name, flds, fld_qry_key).Crt_str(fld_qry_key, key).Exec_select__rls_auto();
|
||||
try {return rdr.Move_next() ? rdr.Read_int(fld_qry_idx) : -1;}
|
||||
finally {rdr.Rls();}
|
||||
}
|
||||
public void Insert(int qry_idx, int rng_end, String qry_key, String qry_data, String qry_name) {
|
||||
conn.Stmt_insert(tbl_name, flds).Val_int(fld_qry_idx, qry_idx).Val_int(fld_rng_end, rng_end)
|
||||
.Val_str(fld_qry_key, qry_key).Val_str(fld_qry_data, qry_data).Val_str(fld_qry_name, qry_name).Exec_insert();
|
||||
}
|
||||
public void Delete_by_qry_idx(int qry_idx) {conn.Stmt_delete(tbl_name, fld_qry_idx).Crt_int(fld_qry_idx, qry_idx).Exec_delete();}
|
||||
public void Rls() {}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
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.wikis.pages.randoms.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.randoms.*;
|
||||
public class Rndm_rng_itm {
|
||||
public Rndm_rng_itm(int mgr_idx, int rng_idx, int seq_bgn, int seq_end) {
|
||||
this.mgr_idx = mgr_idx; this.rng_idx = rng_idx;
|
||||
this.seq_bgn = seq_bgn; this.seq_end = seq_end;
|
||||
}
|
||||
public int Mgr_idx() {return mgr_idx;} private final int mgr_idx;
|
||||
public int Rng_idx() {return rng_idx;} private final int rng_idx;
|
||||
public int Seq_bgn() {return seq_bgn;} private final int seq_bgn;
|
||||
public int Seq_end() {return seq_end;} private final int seq_end;
|
||||
|
||||
public static Rndm_rng_itm Noop() {return new Rndm_rng_itm(-1, -1, 0, 0);}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
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.wikis.pages.randoms.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.randoms.*;
|
||||
import gplx.core.ios.*; import gplx.dbs.*; import gplx.dbs.utls.*;
|
||||
public class Rndm_rng_tbl implements Rls_able {
|
||||
private final String tbl_name = "rndm_rng"; private final Dbmeta_fld_list flds = new Dbmeta_fld_list();
|
||||
private final String fld_qry_idx, fld_rng_idx, fld_seq_bgn, fld_seq_end;
|
||||
private final Db_conn conn;
|
||||
public Rndm_rng_tbl(Db_conn conn) {
|
||||
this.conn = conn;
|
||||
fld_qry_idx = flds.Add_int("qry_idx");
|
||||
fld_rng_idx = flds.Add_int("rng_idx");
|
||||
fld_seq_bgn = flds.Add_int("seq_bgn");
|
||||
fld_seq_end = flds.Add_int("seq_end");
|
||||
conn.Rls_reg(this);
|
||||
}
|
||||
public void Create_tbl() {conn.Meta_tbl_create(Dbmeta_tbl_itm.New(tbl_name, flds));}
|
||||
public void Create_idx() {conn.Meta_idx_create(tbl_name, "core", fld_qry_idx, fld_seq_bgn, fld_seq_end);}
|
||||
public Rndm_rng_itm Select_by_rng_idx_or_noop(int qry_idx, int rng_idx) {
|
||||
Db_rdr rdr = conn.Stmt_select(tbl_name, flds, fld_rng_idx).Crt_int(fld_rng_idx, rng_idx).Exec_select__rls_auto();
|
||||
try {return Load_or_noop(rdr);}
|
||||
finally {rdr.Rls();}
|
||||
}
|
||||
public Rndm_rng_itm Select_by_rndm_num_or_noop(int qry_idx, int rndm_num) {
|
||||
Db_rdr rdr = conn.Stmt_sql(String_.Format("SELECT * FROM rndm_rng WHERE qry_idx = {0} AND seq_bgn <= {1} AND seq_end > {2}", qry_idx, rndm_num)).Exec_select__rls_auto(); // ANSI.Y
|
||||
try {return Load_or_noop(rdr);}
|
||||
finally {rdr.Rls();}
|
||||
}
|
||||
private Rndm_rng_itm Load_or_noop(Db_rdr rdr) {
|
||||
return (rdr.Move_next())
|
||||
? new Rndm_rng_itm(rdr.Read_int(fld_qry_idx), rdr.Read_int(fld_rng_idx), rdr.Read_int(fld_seq_bgn), rdr.Read_int(fld_seq_end))
|
||||
: Rndm_rng_itm.Noop();
|
||||
}
|
||||
public Db_stmt Insert_stmt() {return conn.Stmt_insert(tbl_name, flds);}
|
||||
public void Insert(Db_stmt stmt, int qry_idx, int rng_idx, int seq_bgn, int seq_end) {
|
||||
stmt.Clear().Val_int(fld_qry_idx, qry_idx).Val_int(fld_rng_idx, rng_idx).Val_int(fld_seq_bgn, seq_bgn).Val_int(fld_seq_end, seq_end).Exec_insert();
|
||||
}
|
||||
public void Delete_by_qry_idx(int qry_idx) {conn.Stmt_delete(tbl_name, fld_qry_idx).Crt_int(fld_qry_idx, qry_idx).Exec_delete();}
|
||||
public void Rls() {}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
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.wikis.pages.randoms.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.randoms.*;
|
||||
import gplx.core.ios.*; import gplx.dbs.*; import gplx.dbs.utls.*;
|
||||
public class Rndm_seq_tbl implements Rls_able { // list of page_ids w/ random_idx; EX: 0,123|1,23|2,31|...
|
||||
private final String fld_qry_idx, fld_rng_idx, fld_seq_idx, fld_page_id;
|
||||
private final Db_conn conn;
|
||||
public Rndm_seq_tbl(Db_conn conn) {
|
||||
this.conn = conn;
|
||||
fld_qry_idx = flds.Add_int("qry_idx");
|
||||
fld_rng_idx = flds.Add_int("rng_idx");
|
||||
fld_seq_idx = flds.Add_int("seq_idx");
|
||||
fld_page_id = flds.Add_int("page_id");
|
||||
}
|
||||
public Db_conn Conn() {return conn;}
|
||||
public String Tbl_name() {return tbl_name;} private final String tbl_name = "rndm_seq";
|
||||
public Dbmeta_fld_list Flds() {return flds;} private final Dbmeta_fld_list flds = new Dbmeta_fld_list();
|
||||
public String Fld__qry_idx() {return fld_qry_idx;}
|
||||
public String Fld__rng_idx() {return fld_rng_idx;}
|
||||
public void Create_tbl() {conn.Meta_tbl_create(Dbmeta_tbl_itm.New(tbl_name, flds));}
|
||||
public void Create_idx() {conn.Meta_idx_create(tbl_name, "core", fld_qry_idx, fld_rng_idx, fld_seq_idx);}
|
||||
public int Select_or_neg_1(int qry_idx, int rng_idx, int seq_idx) {
|
||||
Db_stmt stmt = conn.Stmt_select(tbl_name, flds, fld_qry_idx, fld_rng_idx, fld_seq_idx);
|
||||
Db_rdr rdr = stmt.Clear().Crt_int(fld_qry_idx, qry_idx).Crt_int(fld_rng_idx, rng_idx).Val_int(fld_seq_idx, seq_idx).Exec_select__rls_auto();
|
||||
try {return rdr.Move_next() ? rdr.Read_int(fld_page_id) : -1;}
|
||||
catch (Exception e) {Gfo_usr_dlg_.Instance.Warn_many("", "", "failed to get seq_idx; url=~{0} qry_idx=~{1} rng_idx=~{2} seq_idx=~{3} err=~{4}", conn.Conn_info().Db_api(), qry_idx, rng_idx, seq_idx, Err_.Message_gplx_log(e)); return -1;}
|
||||
finally {rdr.Rls();}
|
||||
}
|
||||
public Db_stmt Insert_stmt() {return conn.Stmt_insert(tbl_name, flds);}
|
||||
public void Insert(Db_stmt stmt, int qry_idx, int rng_idx, int seq_idx, int page_id) {
|
||||
stmt.Clear().Val_int(fld_qry_idx, qry_idx).Val_int(fld_rng_idx, rng_idx).Val_int(fld_seq_idx, seq_idx).Val_int(fld_page_id, page_id).Exec_insert();
|
||||
}
|
||||
public void Delete_by_qry_idx(int qry_idx) {conn.Stmt_delete(tbl_name, fld_qry_idx).Crt_int(fld_qry_idx, qry_idx).Exec_delete();}
|
||||
public void Rls() {}
|
||||
|
||||
public static final int Db_row_size_fixed = 4 * 4;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
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.wikis.pages.randoms.mgrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.randoms.*;
|
||||
import gplx.dbs.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
import gplx.xowa.addons.wikis.pages.randoms.dbs.*; import gplx.xowa.addons.wikis.pages.randoms.bldrs.*;
|
||||
public class Rndm_mgr {
|
||||
public Rndm_mgr(Xow_wiki wiki) {
|
||||
this.db_mgr = new Rndm_db_mgr(wiki).Init();
|
||||
}
|
||||
public Rndm_db_mgr Db_mgr() {return db_mgr;} private Rndm_db_mgr db_mgr;
|
||||
|
||||
public int Get_rndm_page(int qry_idx) {
|
||||
// 0|type:ns,ns_id:123,text:123|123
|
||||
int rng_end = db_mgr.Tbl__qry().Select_rng_end(qry_idx);
|
||||
Rndm_rng_itm rng_end_itm = db_mgr.Tbl__rng().Select_by_rng_idx_or_noop(qry_idx, rng_end);
|
||||
int rndm_num = RandomAdp_.new_().Next(rng_end_itm.Seq_end());
|
||||
Rndm_rng_itm rng_itm = db_mgr.Tbl__rng().Select_by_rndm_num_or_noop(qry_idx, rndm_num);
|
||||
int seq_idx = rndm_num - rng_itm.Seq_bgn();
|
||||
int page_id = db_mgr.Tbl__seq().Select_or_neg_1(qry_idx, rng_itm.Rng_idx(), seq_idx);
|
||||
Gfo_log_.Instance.Info("get_random_page", "qry_idx", qry_idx, "rng_end", rng_end, "rndm_num", rndm_num, "rng_idx", rng_itm.Rng_idx(), "seq_idx", seq_idx, "page_id", page_id);
|
||||
return page_id;
|
||||
}
|
||||
public Rndm_bldr_wkr New_bldr() {return new Rndm_bldr_wkr(db_mgr.Conn(), db_mgr.Tbl__qry(), db_mgr.Tbl__rng(), db_mgr.Tbl__seq());}
|
||||
|
||||
public static final int Qry_idx__main = 0; // all
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
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.wikis.pages.randoms.mgrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.randoms.*;
|
||||
import gplx.core.lists.hashs.*;
|
||||
class Rndm_ns_mgr {
|
||||
// private final Hash_adp__int hash = new Hash_adp__int();
|
||||
// public Rndm_ns_itm Get_by_ns(int ns_id) {return (Rndm_ns_itm)hash.Get_by_or_null(ns_id);}
|
||||
public void Add() { // rndm;
|
||||
/*
|
||||
for (mgr : rndm_mgr)
|
||||
hash.Add(mgr,);
|
||||
*/
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
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.wikis.pages.randoms.specials; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.randoms.*;
|
||||
import gplx.xowa.specials.*; import gplx.xowa.wikis.nss.*;
|
||||
public class Rndm_page_special implements Xow_special_page {
|
||||
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;
|
||||
Xow_ns ns = wiki.Ns_mgr().Names_get_or_main(ttl.Rest_txt());
|
||||
// Rndm_addon.Get(wiki).Mgr().Get_rndm_page_by_ns(ns);
|
||||
|
||||
byte[] random_ttl_bry = wiki.Db_mgr().Load_mgr().Find_random_ttl(ns);
|
||||
wiki.Data_mgr().Redirect(page, ns.Gen_ttl(random_ttl_bry));
|
||||
}
|
||||
|
||||
public static final String SPECIAL_KEY = "Randompage"; // NOTE: needs to match lang.gfs
|
||||
public static final byte[] Display_ttl = Bry_.new_a7("Random Page");
|
||||
public Xow_special_meta Special__meta() {return new Xow_special_meta(Xow_special_meta_.Src__mw, SPECIAL_KEY, "random");}
|
||||
public static final Xow_special_page Prototype = new Rndm_page_special();
|
||||
public Xow_special_page Special__clone() {return this;}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
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.wikis.pages.randoms.specials; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.randoms.*;
|
||||
import gplx.xowa.wikis.nss.*; import gplx.xowa.specials.*;
|
||||
public class Rndm_root_special implements Xow_special_page {
|
||||
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;
|
||||
Xow_ns ns = wiki.Ns_mgr().Names_get_or_main(ttl.Rest_txt());
|
||||
// Rndm_addon.Get(wiki).Mgr().Regy().Get_rndm_page_by_ns(ns);
|
||||
byte[] random_ttl_bry = wiki.Db_mgr().Load_mgr().Find_random_ttl(ns);
|
||||
byte[] root_bry = Xoa_ttl.parse(wiki, random_ttl_bry).Root_txt();
|
||||
wiki.Data_mgr().Redirect(page, ns.Gen_ttl(root_bry));
|
||||
}
|
||||
|
||||
public static final String SPECIAL_KEY = "RandomRootPage";
|
||||
public static final byte[] Display_ttl = Bry_.new_a7("Random Root Page");
|
||||
public Xow_special_meta Special__meta() {return new Xow_special_meta(Xow_special_meta_.Src__mw, SPECIAL_KEY);}
|
||||
public static final Xow_special_page Prototype = new Rndm_root_special();
|
||||
public Xow_special_page Special__clone() {return this;}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
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.wikis.pages.randoms.specials; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.randoms.*;
|
||||
import org.junit.*; import gplx.xowa.specials.*;
|
||||
public class Rndm_root_special_tst {
|
||||
@Before public void init() {fxt.Clear();} private Rndm_root_special_fxt fxt = new Rndm_root_special_fxt();
|
||||
@Test public void Ns_main() {
|
||||
fxt.Init_create_page("A");
|
||||
fxt.Init_create_page("A/B/C");
|
||||
fxt.Test_open("Special:RandomRootPage/Main", "A"); // NOTE: result will always be "A"; "A" -> "A"; "A/B/C" -> "A"
|
||||
}
|
||||
@Test public void Ns_help() {
|
||||
fxt.Init_create_page("Help:A");
|
||||
fxt.Init_create_page("Help:A/B/C");
|
||||
fxt.Test_open("Special:RandomRootPage/Help", "Help:A");
|
||||
}
|
||||
}
|
||||
class Rndm_root_special_fxt {
|
||||
private Xop_fxt parser_fxt; private Rndm_root_special special_page; private Xowe_wiki wiki;
|
||||
public void Clear() {
|
||||
parser_fxt = new Xop_fxt();
|
||||
parser_fxt.Reset();
|
||||
wiki = parser_fxt.Wiki();
|
||||
special_page = new gplx.xowa.addons.wikis.pages.randoms.specials.Rndm_root_special();
|
||||
}
|
||||
public void Init_create_page(String page) {parser_fxt.Init_page_create(page, page);}
|
||||
public void Test_open(String special_url, String expd) {
|
||||
Xoae_page page = Test_special_open(wiki, special_page, special_url);
|
||||
Tfds.Eq(expd, String_.new_a7(page.Url().Page_bry()));
|
||||
Tfds.Eq(expd, String_.new_a7(page.Data_raw()));
|
||||
}
|
||||
public static Xoae_page Test_special_open(Xowe_wiki wiki, Xow_special_page special_page, String special_url) {
|
||||
Xoae_page page = wiki.Parser_mgr().Ctx().Page();
|
||||
Xoa_url url = wiki.Utl__url_parser().Parse(Bry_.new_u8(special_url));
|
||||
page.Url_(url);
|
||||
Xoa_ttl ttl = Xoa_ttl.parse(wiki, Bry_.new_a7(special_url));
|
||||
page.Ttl_(ttl);
|
||||
special_page.Special__gen(wiki, page, url, ttl);
|
||||
return page;
|
||||
}
|
||||
}
|
||||
@@ -1,91 +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.wikis.randoms; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*;
|
||||
import gplx.core.primitives.*; import gplx.core.brys.fmtrs.*;
|
||||
import gplx.dbs.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
import gplx.xowa.addons.wikis.randoms.dbs.*;
|
||||
public class Rndm_mgr implements Rls_able {
|
||||
private Rndm_core_tbl core_tbl; private final Rndm_core_row core_row = new Rndm_core_row();
|
||||
private Rndm_range_tbl rng_tbl;
|
||||
private Xowd_page_tbl page_tbl; private Db_stmt stmt__page__random;
|
||||
public void Init(Db_conn conn, Xowd_page_tbl page_tbl) {
|
||||
core_tbl = new Rndm_core_tbl(conn);
|
||||
rng_tbl = new Rndm_range_tbl(conn);
|
||||
this.page_tbl = page_tbl;
|
||||
conn.Rls_reg(this);
|
||||
}
|
||||
public void Rebuild(int uid, String where_sql, int interval) {
|
||||
int total_count = 0; List_adp rng_list = List_adp_.new_();
|
||||
Db_conn conn = page_tbl.conn;
|
||||
Db_stmt stmt = conn.Stmt_select_order(page_tbl.Tbl_name(), String_.Ary(page_tbl.Fld_page_id()), String_.Ary_empty, page_tbl.Fld_page_id());
|
||||
Db_rdr rdr = stmt.Exec_select__rls_auto();
|
||||
try {
|
||||
while (rdr.Move_next()) {
|
||||
++total_count; // add to total count first so (total_count % interval) is never 0 for total_count = 0
|
||||
if (total_count % interval == 0) {
|
||||
int cur_page_id = rdr.Read_int(page_tbl.Fld_page_id());
|
||||
rng_list.Add(Int_obj_ref.new_(cur_page_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {rdr.Rls();}
|
||||
conn.Txn_bgn("rndm_rebuild");
|
||||
core_tbl.Upsert(uid, where_sql, total_count, interval);
|
||||
int rng_ary_len = rng_list.Count();
|
||||
rng_tbl.Insert_bgn(uid);
|
||||
for (int i = 0; i < rng_ary_len; ++i) {
|
||||
Int_obj_ref rng_itm = (Int_obj_ref)rng_list.Get_at(i);
|
||||
rng_tbl.Insert_itm(uid, i + 1, rng_itm.Val());
|
||||
}
|
||||
rng_tbl.Insert_end();
|
||||
conn.Txn_end();
|
||||
}
|
||||
public int Get_rndm_page(int uid) { // EX: ns=0;type_is_redirect=0
|
||||
synchronized (core_row) {core_tbl.Select(core_row, uid);}
|
||||
int rndm_num = RandomAdp_.new_().Next(core_row.total);
|
||||
int rng_idx = rndm_num / core_row.interval;
|
||||
int itm_idx = rndm_num % core_row.interval;
|
||||
int page_id_bgn = rng_idx == 0 ? 0 : rng_tbl.Select_or_neg_1(uid, rng_idx);
|
||||
int rv = Select_by_offset(core_row.where_sql, page_id_bgn, itm_idx);
|
||||
return rv;
|
||||
}
|
||||
private int Select_by_offset(String where_sql, int page_id_bgn, int offset) {
|
||||
Bry_bfr bfr = Bry_bfr.new_();
|
||||
where_sql = fmt_where.Fmt_(where_sql).Bld_many_to_str(bfr, page_tbl.Fld_page_ns(), page_tbl.Fld_is_redirect());
|
||||
String sql = fmt_sql.Bld_many_to_str(bfr, page_tbl.Tbl_name(), page_tbl.Fld_page_id(), where_sql, page_id_bgn, offset);
|
||||
Db_rdr rdr = Db_rdr_.Empty;
|
||||
try {
|
||||
rdr = page_tbl.conn.Exec_rdr(sql);
|
||||
return rdr.Move_next() ? rdr.Read_int(page_tbl.Fld_page_id()) : -1;
|
||||
}
|
||||
finally {rdr.Rls();}
|
||||
}
|
||||
public void Rls() {
|
||||
stmt__page__random = Db_stmt_.Rls(stmt__page__random);
|
||||
}
|
||||
private static final Bry_fmt fmt_sql = Bry_fmt.New(String_.Concat_lines_nl_skip_last
|
||||
( "SELECT p.~{page_id}"
|
||||
, "FROM ~{page} p"
|
||||
, "WHERE p.~{~page_id} > ~{page_id_bgn}"
|
||||
, "~{where_sql}"
|
||||
, "ORDER BY ~{page_id}"
|
||||
, "LIMIT 1"
|
||||
, "OFFSET ~{offset};"
|
||||
), "page", "page_id", "where_sql", "page_id_bgn", "offset");
|
||||
private static final Bry_fmt fmt_where = Bry_fmt.New("", "page_namespace", "page_is_redirect");
|
||||
}
|
||||
@@ -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.wikis.randoms.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.randoms.*;
|
||||
import gplx.core.ios.*; import gplx.dbs.*; import gplx.dbs.utls.*;
|
||||
public class Rndm_core_tbl implements Rls_able {
|
||||
private final String tbl_name = "rndm_core"; private final Dbmeta_fld_list flds = Dbmeta_fld_list.new_();
|
||||
private final String fld_uid, fld_where_sql, fld_total, fld_interval;
|
||||
private final Db_conn conn; private Db_stmt stmt_select;
|
||||
public Rndm_core_tbl(Db_conn conn) {
|
||||
this.conn = conn;
|
||||
fld_uid = flds.Add_int_pkey("rndm_uid");
|
||||
fld_where_sql = flds.Add_str("rndm_where_sql", 1024);
|
||||
fld_total = flds.Add_int("rndm_total");
|
||||
fld_interval = flds.Add_int("rndm_interval");
|
||||
conn.Rls_reg(this);
|
||||
}
|
||||
public void Create_tbl() {conn.Meta_tbl_create(Dbmeta_tbl_itm.New(tbl_name, flds, Dbmeta_idx_itm.new_unique_by_name(tbl_name, "core", fld_uid)));}
|
||||
public void Upsert(int uid, String where_sql, int total, int interval) {
|
||||
conn.Stmt_delete(tbl_name, fld_uid).Crt_int(fld_uid, uid).Exec_delete();
|
||||
conn.Stmt_insert(tbl_name, flds).Val_int(fld_uid, uid).Val_str(fld_where_sql, where_sql).Val_int(fld_total, total).Val_int(fld_interval, interval).Exec_insert();
|
||||
}
|
||||
public void Select(Rndm_core_row rv, int uid) {
|
||||
if (stmt_select == null) stmt_select = conn.Stmt_select(tbl_name, flds, fld_uid);
|
||||
Db_rdr rdr = stmt_select.Clear().Val_int(fld_uid, uid).Exec_select__rls_manual();
|
||||
try {
|
||||
if (rdr.Move_next()) {
|
||||
String where_sql = rdr.Read_str(fld_where_sql);
|
||||
int total = rdr.Read_int(fld_total);
|
||||
int interval = rdr.Read_int(fld_interval);
|
||||
rv.Load(uid, where_sql, total, interval);
|
||||
}
|
||||
} finally {rdr.Rls();}
|
||||
}
|
||||
public void Rls() {
|
||||
stmt_select = Db_stmt_.Rls(stmt_select);
|
||||
}
|
||||
}
|
||||
@@ -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.wikis.randoms.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.randoms.*;
|
||||
import gplx.core.ios.*; import gplx.dbs.*; import gplx.dbs.utls.*;
|
||||
public class Rndm_range_tbl implements Rls_able {
|
||||
private final String tbl_name = "rndm_range"; private final Dbmeta_fld_list flds = Dbmeta_fld_list.new_();
|
||||
private final String fld_rng_uid, fld_rng_idx, fld_rng_page_id;
|
||||
private final Db_conn conn; private Db_stmt stmt_select, stmt_insert;
|
||||
public Rndm_range_tbl(Db_conn conn) {
|
||||
this.conn = conn;
|
||||
fld_rng_uid = flds.Add_int("rng_uid");
|
||||
fld_rng_idx = flds.Add_int("rng_idx");
|
||||
fld_rng_page_id = flds.Add_int("rng_page_id");
|
||||
conn.Rls_reg(this);
|
||||
}
|
||||
public void Create_tbl() {conn.Meta_tbl_create(Dbmeta_tbl_itm.New(tbl_name, flds, Dbmeta_idx_itm.new_unique_by_name(tbl_name, "core", fld_rng_uid, fld_rng_idx)));}
|
||||
public void Insert_bgn(int uid) {
|
||||
conn.Stmt_delete(tbl_name, fld_rng_uid).Crt_int(fld_rng_uid, uid).Exec_delete();
|
||||
stmt_insert = conn.Stmt_insert(tbl_name, flds);
|
||||
}
|
||||
public void Insert_itm(int uid, int idx, int page_id) {
|
||||
stmt_insert.Clear().Val_int(fld_rng_uid, uid).Val_int(fld_rng_idx, idx).Val_int(fld_rng_page_id, page_id).Exec_insert();
|
||||
}
|
||||
public void Insert_end() {
|
||||
stmt_insert = Db_stmt_.Rls(stmt_insert);
|
||||
}
|
||||
public int Select_or_neg_1(int core_uid, int rng_idx) {
|
||||
if (stmt_select == null) stmt_select = conn.Stmt_select(tbl_name, flds, fld_rng_uid, fld_rng_idx);
|
||||
Db_rdr rdr = stmt_select.Clear().Val_int(fld_rng_uid, core_uid).Val_int(fld_rng_idx, rng_idx).Exec_select__rls_manual();
|
||||
try {return rdr.Move_next() ? rdr.Read_int(fld_rng_page_id) : -1;}
|
||||
catch (Exception e) {Gfo_usr_dlg_.Instance.Warn_many("", "", "failed to get rndm_idx; url=~{0} core_uid=~{1} rng_idx=~{2} err=~{3}", conn.Conn_info().Db_api(), core_uid, rng_idx, Err_.Message_gplx_log(e)); return -1;}
|
||||
finally {rdr.Rls();}
|
||||
}
|
||||
public void Rls() {
|
||||
stmt_select = Db_stmt_.Rls(stmt_select);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
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.wikis.registrys; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*;
|
||||
import gplx.xowa.specials.*;
|
||||
public class Wiki_registry_addon implements Xoax_addon_itm, Xoax_addon_itm__special {
|
||||
public Xow_special_page[] Special_pages() {
|
||||
return new Xow_special_page[]
|
||||
{ gplx.xowa.addons.wikis.registrys.lists.Xow_list_special.Prototype
|
||||
, gplx.xowa.addons.wikis.registrys.infos.Xow_info_special.Prototype
|
||||
};
|
||||
}
|
||||
|
||||
public String Addon__key() {return "xowa.apps.wikis.registrys";}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.wikis.registrys.infos; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.registrys.*;
|
||||
import gplx.langs.mustaches.*;
|
||||
class Xow_info_doc implements Mustache_doc_itm {
|
||||
private final Mustache_doc_itm[] ary;
|
||||
public Xow_info_doc(Xow_info_doc_wiki itm) {this.ary = new Mustache_doc_itm[] {itm};}
|
||||
public boolean Mustache__write(String key, Mustache_bfr bfr) {return false;}
|
||||
public Mustache_doc_itm[] Mustache__subs(String key) {
|
||||
if (String_.Eq(key, "wiki_info")) return ary;
|
||||
return Mustache_doc_itm_.Ary__empty;
|
||||
}
|
||||
}
|
||||
class Xow_info_doc_wiki implements Mustache_doc_itm {
|
||||
private final byte[] domain;
|
||||
private final String date, size, dir;
|
||||
public Xow_info_doc_wiki(byte[] domain, String date, String dir, String size) {
|
||||
this.domain = domain; this.date = date; this.dir = dir; this.size = size;
|
||||
}
|
||||
public boolean Mustache__write(String key, Mustache_bfr bfr) {
|
||||
if (String_.Eq(key, "wiki_domain")) bfr.Add_bry(domain);
|
||||
else if (String_.Eq(key, "wiki_date")) bfr.Add_str_u8(date);
|
||||
else if (String_.Eq(key, "wiki_dir")) bfr.Add_str_u8(dir);
|
||||
else if (String_.Eq(key, "wiki_size")) bfr.Add_str_u8(size);
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
public Mustache_doc_itm[] Mustache__subs(String key) {return Mustache_doc_itm_.Ary__empty;}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
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.wikis.registrys.infos; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.registrys.*;
|
||||
import gplx.xowa.specials.*; import gplx.langs.mustaches.*; import gplx.xowa.wikis.pages.*; import gplx.xowa.wikis.pages.tags.*;
|
||||
import gplx.xowa.users.data.*;
|
||||
class Xow_info_html extends Xow_special_wtr__base {
|
||||
private final byte[] wiki_domain;
|
||||
public Xow_info_html(byte[] wiki_domain) {this.wiki_domain = wiki_domain;}
|
||||
@Override protected Io_url Get_addon_dir(Xoa_app app) {return app.Fsys_mgr().Http_root().GenSubDir_nest("bin", "any", "xowa", "addon", "wiki", "registry", "info");}
|
||||
@Override protected Io_url Get_mustache_fil(Io_url addon_dir) {return addon_dir.GenSubFil_nest("bin", "xow_info.mustache.html");}
|
||||
@Override protected Mustache_doc_itm Bld_mustache_root(Xoa_app app) {
|
||||
// load itm from db
|
||||
app.User().User_db_mgr().Init_site_mgr(); // HACK.USER_DB: init site_mgr for desktop
|
||||
Xoud_site_row site_itm = app.User().User_db_mgr().Site_mgr().Select_by_domain(wiki_domain);
|
||||
if (site_itm == null) return null; // handle deleted wikis
|
||||
String wiki_dir = site_itm.Path();
|
||||
if (String_.Eq(site_itm.Date(), "")) {
|
||||
Xow_wiki wiki = app.Wiki_mgri().Get_by_or_make_init_n(wiki_domain);
|
||||
wiki.Init_by_wiki(); // force init to load Modified_latest
|
||||
site_itm.Date_(wiki.Props().Modified_latest__yyyy_MM_dd());
|
||||
app.User().User_db_mgr().Site_mgr().Update(site_itm);
|
||||
}
|
||||
return new Xow_info_doc
|
||||
( new Xow_info_doc_wiki(wiki_domain, site_itm.Date(), wiki_dir
|
||||
, Calc_file_size(Io_url_.new_dir_(wiki_dir)))
|
||||
);
|
||||
}
|
||||
@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());
|
||||
head_tags.Add(Xopg_tag_itm.New_css_file(addon_dir.GenSubFil_nest("bin", "xow_info.css")));
|
||||
}
|
||||
@Override protected void Handle_invalid(Xoa_app app, Xoa_page page, Xow_special_page special) {
|
||||
new Xopage_html_data(special.Special__meta().Display_ttl(), Bry_.Add(wiki_domain, Bry_.new_a7(" has been deleted"))).Apply(page);
|
||||
}
|
||||
|
||||
private static String Calc_file_size(Io_url dir) {
|
||||
Io_url[] urls = Io_mgr.Instance.QueryDir_fils(dir);
|
||||
int len = urls.length;
|
||||
long size = 0;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Io_url url = urls[i];
|
||||
size += Io_mgr.Instance.QueryFil(url).Size();
|
||||
}
|
||||
return gplx.core.ios.Io_size_.To_str_new(Bry_bfr_.New(), size, 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
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.wikis.registrys.infos; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.registrys.*;
|
||||
import gplx.xowa.specials.*; import gplx.core.net.*; import gplx.core.net.qargs.*; import gplx.xowa.wikis.pages.*;
|
||||
public class Xow_info_special implements Xow_special_page {
|
||||
public void Special__gen(Xow_wiki wiki, Xoa_page page, Xoa_url url, Xoa_ttl ttl) {
|
||||
Gfo_qarg_mgr url_args = new Gfo_qarg_mgr().Init(url.Qargs_ary());
|
||||
|
||||
// if cmd=delete passed; delete "wiki"
|
||||
byte[] wiki_domain = url_args.Read_bry_or_fail("wiki");
|
||||
if (url_args.Read_enm_as_int_or(Enm_cmd.Itm, -1) == Enm_cmd.Tid__delete) {
|
||||
wiki.App().User().User_db_mgr().Site_mgr().Delete_by_domain(wiki_domain);
|
||||
Xow_wiki delete_wiki = wiki.App().Wiki_mgri().Get_by_or_make_init_n(wiki_domain);
|
||||
if (delete_wiki != null) { // guard against revisiting url for deleted wiki
|
||||
if (delete_wiki.Data__core_mgr() != null) // null check needed in case wiki is not loaded
|
||||
delete_wiki.Data__core_mgr().Rls(); // release connection if open
|
||||
Delete_wiki_files(delete_wiki.Fsys_mgr().Root_dir());
|
||||
}
|
||||
page.Redirect_to_ttl_(gplx.xowa.addons.wikis.registrys.lists.Xow_list_special.Prototype.Special__meta().Ttl_bry());
|
||||
return;
|
||||
}
|
||||
|
||||
// show info of wikis
|
||||
new Xow_info_html(wiki_domain).Bld_page_by_mustache(wiki.App(), page, this);
|
||||
}
|
||||
private static void Delete_wiki_files(Io_url root_dir) {
|
||||
Io_url[] urls = Io_mgr.Instance.QueryDir_fils(root_dir);
|
||||
for (Io_url url : urls) {
|
||||
try {
|
||||
Io_mgr.Instance.DeleteFil(url);
|
||||
} catch (Exception e) {
|
||||
Gfo_log_.Instance.Warn("failed to delete wiki file", "wiki", url.Raw(), "err", Err_.Message_gplx_log(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class Enm_cmd {//#*nested
|
||||
public static final int Tid__delete = 0;
|
||||
public static final Gfo_qarg_enum_itm Itm = new Gfo_qarg_enum_itm("cmd").Add("delete", Tid__delete);
|
||||
}
|
||||
|
||||
Xow_info_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 Xow_info_special(Xow_special_meta.New_xo("XowaWikiInfo", "Wiki Info"));
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
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.wikis.registrys.lists; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.registrys.*;
|
||||
import gplx.langs.mustaches.*;
|
||||
class Xow_list_doc implements Mustache_doc_itm {
|
||||
private final byte[] import_root;
|
||||
private final Xow_list_doc_wiki[] subs;
|
||||
public Xow_list_doc(byte[] import_root, Xow_list_doc_wiki[] 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 Xow_list_doc_wiki implements Mustache_doc_itm {
|
||||
private final byte[] domain;
|
||||
private final String date;
|
||||
public Xow_list_doc_wiki(byte[] domain, String 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_str_u8(date);
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
public Mustache_doc_itm[] Mustache__subs(String key) {return Mustache_doc_itm_.Ary__empty;}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
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.wikis.registrys.lists; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.registrys.*;
|
||||
import gplx.xowa.specials.*; import gplx.langs.mustaches.*; import gplx.xowa.wikis.pages.*; import gplx.xowa.wikis.pages.tags.*;
|
||||
import gplx.xowa.wikis.xwikis.*;
|
||||
import gplx.xowa.users.data.*;
|
||||
class Xow_list_html extends Xow_special_wtr__base {
|
||||
@Override protected Io_url Get_addon_dir(Xoa_app app) {return app.Fsys_mgr().Http_root().GenSubDir_nest("bin", "any", "xowa", "addon", "wiki", "registry", "list");}
|
||||
@Override protected Io_url Get_mustache_fil(Io_url addon_dir) {return addon_dir.GenSubFil_nest("bin", "xow_list.mustache.html");}
|
||||
@Override protected Mustache_doc_itm Bld_mustache_root(Xoa_app app) {
|
||||
// make list_mgr based on site_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 Xow_list_doc_wiki(Bry_.new_u8(site_itm.Domain()), site_itm.Date()));
|
||||
}
|
||||
return new Xow_list_doc(Get_root_url(), (Xow_list_doc_wiki[])list.To_ary_and_clear(Xow_list_doc_wiki.class));
|
||||
}
|
||||
@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());
|
||||
head_tags.Add(Xopg_tag_itm.New_css_file(addon_dir.GenSubFil_nest("bin", "xow_list.css")));
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.wikis.registrys.lists; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.registrys.*;
|
||||
import gplx.xowa.specials.*; import gplx.core.net.*; import gplx.core.net.qargs.*; import gplx.xowa.wikis.pages.*;
|
||||
public class Xow_list_special implements Xow_special_page {
|
||||
public void Special__gen(Xow_wiki wiki, Xoa_page page, Xoa_url url, Xoa_ttl ttl) {
|
||||
Gfo_qarg_mgr url_args = new Gfo_qarg_mgr().Init(url.Qargs_ary());
|
||||
|
||||
// if cmd=add passed; import "file"; occurs when "file" is selected by file_browser
|
||||
if (url_args.Read_enm_as_int_or(Enm_cmd.Itm, -1) == Enm_cmd.Tid__add) {
|
||||
byte[] file = url_args.Read_bry_or_fail("file");
|
||||
if (wiki.App().Tid_is_edit()) wiki.App().User().User_db_mgr().Init_site_mgr(); // HACK.USER_DB: init site_mgr for desktop
|
||||
wiki.App().Wiki_mgri().Import_by_url(Io_url_.new_fil_(String_.new_u8(file)));
|
||||
}
|
||||
|
||||
// show list of wikis
|
||||
new Xow_list_html().Bld_page_by_mustache(wiki.App(), page, this);
|
||||
}
|
||||
|
||||
static class Enm_cmd {//#*nested
|
||||
public static final int Tid__add = 0;
|
||||
public static final Gfo_qarg_enum_itm Itm = new Gfo_qarg_enum_itm("cmd").Add("add", Tid__add);
|
||||
}
|
||||
|
||||
Xow_list_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 Xow_list_special(Xow_special_meta.New_xo("XowaWikiList", "Wikis", "XowaWikis"));
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
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.wikis.searchs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*;
|
||||
import gplx.xowa.addons.wikis.searchs.dbs.*; import gplx.xowa.addons.wikis.searchs.searchers.*; import gplx.xowa.addons.wikis.searchs.parsers.*; import gplx.xowa.addons.wikis.searchs.searchers.rslts.*; import gplx.xowa.addons.wikis.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 String Addon__key() {return ADDON_KEY;} private static final String ADDON_KEY = "xowa.apps.search";
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
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.wikis.searchs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*;
|
||||
import gplx.xowa.addons.wikis.searchs.searchers.*;
|
||||
import gplx.xowa.addons.wikis.searchs.searchers.rslts.*;
|
||||
public interface Srch_search_addon_api {
|
||||
void Search(Srch_search_qry qry, Srch_rslt_cbk cbk);
|
||||
}
|
||||
109
400_xowa/src/gplx/xowa/addons/wikis/searchs/Srch_search_cfg.java
Normal file
109
400_xowa/src/gplx/xowa/addons/wikis/searchs/Srch_search_cfg.java
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
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.wikis.searchs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*;
|
||||
import gplx.core.net.*; import gplx.core.net.qargs.*;
|
||||
import gplx.xowa.wikis.nss.*;
|
||||
import gplx.xowa.addons.wikis.searchs.searchers.cbks.*; import gplx.xowa.addons.wikis.searchs.searchers.*;
|
||||
public class Srch_search_cfg implements Gfo_invk {
|
||||
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 Gfo_invk_.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
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.wikis.searchs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*;
|
||||
import gplx.xowa.bldrs.wkrs.*; import gplx.xowa.addons.wikis.searchs.bldrs.cmds.*;
|
||||
public class Xoax_builds_search_addon implements Xoax_addon_itm, Xoax_addon_itm__bldr {
|
||||
public Xob_cmd[] Bldr_cmds() {
|
||||
return new Xob_cmd[]
|
||||
{ Xobldr__link__link_score.Prototype
|
||||
, Xobldr__page__page_score.Prototype
|
||||
, Xobldr__word__link_count.Prototype
|
||||
};
|
||||
}
|
||||
|
||||
public String Addon__key() {return "xowa.builds.search";}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
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.wikis.searchs.bldrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.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 Gfo_invk_.Rv_unhandled;
|
||||
return this;
|
||||
} private static final String Invk_progress_interval_ = "progress_interval_", Invk_commit_interval_ = "commit_interval_";
|
||||
}
|
||||
@@ -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.wikis.searchs.bldrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*;
|
||||
import gplx.xowa.bldrs.*;
|
||||
import gplx.xowa.addons.wikis.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.bldrs.pagelinks.bldrs.Pglnk_bldr_cmd.Dump_type_key));
|
||||
bldr.Cmd_mgr().Add_many(wiki, gplx.xowa.addons.bldrs.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"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
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.wikis.searchs.bldrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.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;}
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
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.wikis.searchs.bldrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*;
|
||||
import gplx.dbs.*; import gplx.xowa.wikis.data.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
import gplx.xowa.addons.wikis.searchs.dbs.*; import gplx.xowa.addons.wikis.searchs.parsers.*;
|
||||
class Srch_temp_tbl_wkr implements Srch_text_parser_wkr {
|
||||
private Xowe_wiki wiki; private Xow_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.Conn_main_(word_conn).Conn_others_(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.Conn_main_(link_tbl.conn).Conn_others_(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");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
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.wikis.searchs.bldrs.cmds; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.searchs.bldrs.*;
|
||||
import gplx.dbs.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.wkrs.*; import gplx.xowa.addons.bldrs.utils_rankings.bldrs.*; import gplx.xowa.addons.wikis.searchs.bldrs.cmds.adjustments.*;
|
||||
import gplx.xowa.addons.wikis.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;
|
||||
private final Adjustment_cmd score_adjustment_mgr;
|
||||
public Xobldr__link__link_score(Xob_bldr bldr, Xowe_wiki wiki) {super(bldr, wiki);
|
||||
this.score_adjustment_mgr = new Adjustment_cmd(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_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 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)
|
||||
);
|
||||
|
||||
// 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)"
|
||||
));
|
||||
|
||||
// adjust pages; NOTE: must happen after percentize b/c adjustment is based on percentized 0 : 100,000, not the raw page_rank (0.5 : 146.5)
|
||||
score_adjustment_mgr.Exec();
|
||||
}
|
||||
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"
|
||||
, " AND lsm.mnx_val " + (min ? "<" : ">") + " search_word." + fld_name
|
||||
, " ), " + 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 if (ctx.Match(k, Invk__delete_plink_db_)) delete_plink_db = m.ReadYn("v");
|
||||
else if (ctx.Match(k, Invk__score_adjustment_mgr)) return score_adjustment_mgr;
|
||||
else return Gfo_invk_.Rv_unhandled;
|
||||
return this;
|
||||
}
|
||||
private static final String Invk__page_rank_enabled_ = "page_rank_enabled_", Invk__delete_plink_db_ = "delete_plink_db_"
|
||||
, Invk__score_adjustment_mgr = "score_adjustment_mgr"
|
||||
;
|
||||
|
||||
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);}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
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.wikis.searchs.bldrs.cmds; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.searchs.bldrs.*;
|
||||
import gplx.dbs.*; import gplx.dbs.qrys.*;
|
||||
import gplx.xowa.wikis.data.*; import gplx.xowa.wikis.data.tbls.*; import gplx.xowa.addons.bldrs.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)
|
||||
, Dbmeta_fld_itm.new_int ("page_namespace").Default_(Int_.Min_value)
|
||||
, Dbmeta_fld_itm.new_byte ("page_is_redirect").Default_(0)
|
||||
, Dbmeta_fld_itm.new_int ("page_len").Default_(0)
|
||||
));
|
||||
|
||||
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, page_namespace, page_is_redirect, page_len)"
|
||||
, "SELECT p.page_id"
|
||||
, ", Coalesce(Count(pl.trg_id), {0}) AS link_count"
|
||||
, ", p.page_namespace"
|
||||
, ", p.page_is_redirect"
|
||||
, ", p.page_len"
|
||||
, "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"
|
||||
, "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, page_namespace, page_is_redirect, page_len)"
|
||||
, "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"
|
||||
, ", pr.page_namespace"
|
||||
, ", pr.page_is_redirect"
|
||||
, ", pr.page_len"
|
||||
, "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 Gfo_invk_.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);}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
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.wikis.searchs.bldrs.cmds; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.searchs.bldrs.*;
|
||||
import gplx.dbs.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.wkrs.*; import gplx.xowa.addons.bldrs.utils_rankings.bldrs.*;
|
||||
import gplx.xowa.addons.wikis.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 = Cast((SELECT tpl.row_score FROM search_word__link_count tpl WHERE tpl.row_key = search_word.word_id) AS int)"
|
||||
));
|
||||
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);}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
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.wikis.searchs.bldrs.cmds.adjustments; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.searchs.bldrs.*; import gplx.xowa.addons.wikis.searchs.bldrs.cmds.*;
|
||||
import gplx.dbs.*; import gplx.xowa.bldrs.*;
|
||||
import gplx.xowa.wikis.nss.*;
|
||||
public class Adjustment_cmd implements Gfo_invk {
|
||||
private final Xow_wiki wiki;
|
||||
private final Page_matcher_mgr matcher_mgr;
|
||||
private boolean enabled = true;
|
||||
private double median_factor = .001d;
|
||||
public Adjustment_cmd(Xow_wiki wiki) {
|
||||
this.wiki = wiki;
|
||||
this.matcher_mgr = new Page_matcher_mgr(wiki);
|
||||
}
|
||||
public void Exec() {
|
||||
// init
|
||||
if (!enabled) return;
|
||||
wiki.Init_by_wiki();
|
||||
Xob_db_file pl_db = Xob_db_file.New__page_link(wiki);
|
||||
Db_conn pl_conn = pl_db.Conn();
|
||||
|
||||
// add fields to page_rank_tbl
|
||||
String page_rank_tbl = Xobldr__page__page_score.Pagerank__tbl_name;
|
||||
pl_conn.Meta_fld_assert(page_rank_tbl, "score_old" , Dbmeta_fld_tid.Itm__int, 0);
|
||||
pl_conn.Meta_fld_assert(page_rank_tbl, "len_avg" , Dbmeta_fld_tid.Itm__int, 0);
|
||||
|
||||
// create penalty summary tbl
|
||||
pl_conn.Meta_tbl_remake(Dbmeta_tbl_itm.New("penalty_summary"
|
||||
, Dbmeta_fld_itm.new_int("page_ns")
|
||||
, Dbmeta_fld_itm.new_int("score_bgn")
|
||||
, Dbmeta_fld_itm.new_int("score_end")
|
||||
, Dbmeta_fld_itm.new_int("len_avg")
|
||||
, Dbmeta_fld_itm.new_int("page_count")
|
||||
));
|
||||
Db_stmt summary_stmt = pl_conn.Stmt_insert("penalty_summary", "page_ns", "score_bgn", "score_end", "len_avg", "page_count");
|
||||
Db_stmt detail_stmt = pl_conn.Stmt_update(page_rank_tbl, String_.Ary("page_id"), "page_score", "score_old", "len_avg");
|
||||
|
||||
// iterate namespaces
|
||||
pl_conn.Meta_idx_create("page_rank_temp", "adjustment", "page_namespace", "page_score");
|
||||
Db_stmt page_select = pl_conn.Stmt_sql("SELECT pr.page_id, pr.page_is_redirect, pr.page_len, pr.page_score FROM page_rank_temp pr WHERE pr.page_namespace = ? ORDER BY pr.page_score DESC");// ANSI.Y
|
||||
int ns_len = wiki.Ns_mgr().Ords_len();
|
||||
for (int i = 0; i < ns_len; ++i) {
|
||||
Xow_ns ns = wiki.Ns_mgr().Ords_get_at(i);
|
||||
if (ns.Count() > 0) {
|
||||
Page_matcher_wkr matcher_wkr = matcher_mgr.Get_by(ns.Id()).Load_all();
|
||||
pl_conn.Txn_bgn("pl_penalty");
|
||||
Calc_for_ns(wiki, matcher_wkr, page_select, summary_stmt, detail_stmt, ns);
|
||||
pl_conn.Txn_end();
|
||||
}
|
||||
}
|
||||
|
||||
// cleanup
|
||||
detail_stmt.Rls();
|
||||
summary_stmt.Rls();
|
||||
page_select.Rls();
|
||||
}
|
||||
private void Calc_for_ns(Xow_wiki wiki, Page_matcher_wkr wkr, Db_stmt page_select, Db_stmt summary_stmt, Db_stmt detail_stmt, Xow_ns ns) {
|
||||
// calc sample
|
||||
int sample_len = (int)(ns.Count() * .0001); // 12,000,000 * .0001 -> 1200
|
||||
if (sample_len < 100) sample_len = 100; // if < 100, default to 100; else small sample sizes like 5 will create strange medians
|
||||
Page_stub[] page_ary = new Page_stub[sample_len];
|
||||
|
||||
// loop
|
||||
Gfo_log_.Instance.Prog("loading pages for ns", "ns_id", ns.Id());
|
||||
Db_rdr rdr = page_select.Clear().Crt_int("page_namespace", ns.Id()).Exec_select__rls_manual(); // ANSI.Y
|
||||
int page_count = 0;
|
||||
int score_end = -1, score_cur = -1;
|
||||
int range_count = 0;
|
||||
while (rdr.Move_next()) {
|
||||
int page_id = rdr.Read_int("page_id");
|
||||
boolean page_is_redirect = rdr.Read_bool_by_byte("page_is_redirect");
|
||||
int page_len = rdr.Read_int("page_len");
|
||||
score_cur = rdr.Read_int("page_score");
|
||||
if (score_end == -1) score_end = score_cur;
|
||||
|
||||
page_ary[page_count] = new Page_stub(page_id, page_is_redirect, page_len, score_cur);
|
||||
++page_count;
|
||||
if (page_count == sample_len) {
|
||||
if ((++range_count % 100) == 0) Gfo_log_.Instance.Prog("updating range", "ns", ns.Id(), "score_cur", score_cur, "score_end", score_end);
|
||||
Save_sample(page_ary, wkr, wiki.Domain_bry(), ns.Id(), score_cur, score_end, summary_stmt, detail_stmt);
|
||||
|
||||
// reset
|
||||
page_count = 0;
|
||||
score_end = -1;
|
||||
}
|
||||
}
|
||||
page_ary = (Page_stub[])Array_.Resize(page_ary, page_count);
|
||||
Save_sample(page_ary, wkr, wiki.Domain_bry(), ns.Id(), score_cur, score_end, summary_stmt, detail_stmt);
|
||||
rdr.Rls();
|
||||
}
|
||||
private void Save_sample(Page_stub[] page_ary, Page_matcher_wkr wkr, byte[] domain_bry, int ns_id, int score_cur, int score_end, Db_stmt summary_stmt, Db_stmt detail_stmt) {
|
||||
// calc median
|
||||
Array_.Sort(page_ary);
|
||||
int ary_len = page_ary.length; if (ary_len == 0) return; // occurs when ns has exact multiple of .01% pages; EX: 10,000 pages (but not 10,001, 10,002, etc..)
|
||||
int median = Calc_median(page_ary);
|
||||
|
||||
// insert
|
||||
for (int i = 0; i < ary_len; ++i) {
|
||||
Page_stub page = page_ary[i];
|
||||
int score_old = page.Score;
|
||||
int score_new = score_old;
|
||||
Page_matcher_itm itm = wkr.Get_by_or_null(page.Id);
|
||||
if (itm != null) {
|
||||
score_new = itm.Calc(score_old);
|
||||
}
|
||||
// if len < median, penalize by .01 of difference;
|
||||
/*
|
||||
EX: score=1000; page_len=80; median_len=100
|
||||
.8 <- 80 / 100
|
||||
.2 <- 1 - .8
|
||||
.002 <- .2 * .01
|
||||
2 <- 1000 * .002
|
||||
998 <- 1000 - 2
|
||||
*/
|
||||
else if (page.Len < median)
|
||||
score_new = (int)((1 - (1 - ((double)page.Len / median)) * median_factor) * score_old);
|
||||
|
||||
detail_stmt.Clear()
|
||||
.Val_int("page_score" , score_new)
|
||||
.Val_int("score_old" , score_old)
|
||||
.Val_int("len_avg" , median)
|
||||
.Crt_int("page_id" , page.Id)
|
||||
.Exec_update();
|
||||
}
|
||||
summary_stmt.Clear().Val_int("page_ns", ns_id).Val_int("score_bgn", score_cur).Val_int("score_end", score_end)
|
||||
.Val_int("len_avg", median).Val_int("page_count", ary_len)
|
||||
.Exec_insert();
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk__enabled_)) enabled = m.ReadBool("v");
|
||||
else if (ctx.Match(k, Invk__median_factor_)) median_factor = m.ReadDouble("v");
|
||||
else if (ctx.Match(k, Invk__match_mgr)) return matcher_mgr;
|
||||
else return Gfo_invk_.Rv_unhandled;
|
||||
return this;
|
||||
} private static final String Invk__match_mgr = "match_mgr", Invk__enabled_ = "enabled_", Invk__median_factor_ = "median_factor_";
|
||||
|
||||
private static int Calc_median(Page_stub[] ary) {
|
||||
int len = ary.length;
|
||||
int redirect_end = 0;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Page_stub itm = ary[i];
|
||||
if (!itm.Is_redirect) {
|
||||
redirect_end = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int median_idx = (len - redirect_end) / 2;
|
||||
return ary[median_idx].Len;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
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.wikis.searchs.bldrs.cmds.adjustments; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.searchs.bldrs.*; import gplx.xowa.addons.wikis.searchs.bldrs.cmds.*;
|
||||
import gplx.core.primitives.*;
|
||||
class Page_matcher_itm {
|
||||
public Page_matcher_itm(byte match_type, byte calc_type, double val, String page_filter) {
|
||||
this.Match_type = match_type;
|
||||
this.Calc_type = calc_type;
|
||||
this.Val = val;
|
||||
this.Page_filter = page_filter;
|
||||
}
|
||||
public final byte Match_type;
|
||||
public final byte Calc_type;
|
||||
public final double Val;
|
||||
public final String Page_filter;
|
||||
public Int_obj_ref[] Page_ids;
|
||||
public int Calc(int score_old) {
|
||||
switch (this.Calc_type) {
|
||||
case Page_matcher__calc_type.Type__set : return (int)Val;
|
||||
case Page_matcher__calc_type.Type__mult : return (int)(score_old * Val);
|
||||
case Page_matcher__calc_type.Type__add : return score_old + (int)Val;
|
||||
default: throw Err_.new_unhandled_default(this.Calc_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
class Page_matcher__match_type {
|
||||
public static final byte Type__bgn = 0, Type__end = 1, Type__all = 2, Type__any = 3;
|
||||
public static byte To_tid(String s) {
|
||||
if (String_.Eq(s, "bgn")) return Type__bgn;
|
||||
else if (String_.Eq(s, "end")) return Type__end;
|
||||
else if (String_.Eq(s, "all")) return Type__all;
|
||||
else throw Err_.new_unhandled_default(s);
|
||||
}
|
||||
}
|
||||
class Page_matcher__calc_type {
|
||||
public static final byte Type__set = 0, Type__mult = 1, Type__add = 2;
|
||||
public static byte To_tid(String s) {
|
||||
if (String_.Eq(s, "set")) return Type__set;
|
||||
else if (String_.Eq(s, "mult")) return Type__mult;
|
||||
else if (String_.Eq(s, "add")) return Type__add;
|
||||
else throw Err_.new_unhandled_default(s);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
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.wikis.searchs.bldrs.cmds.adjustments; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.searchs.bldrs.*; import gplx.xowa.addons.wikis.searchs.bldrs.cmds.*;
|
||||
import gplx.core.lists.hashs.*; import gplx.core.primitives.*;
|
||||
import gplx.dbs.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
class Page_matcher_mgr implements Gfo_invk {
|
||||
private final Xow_wiki wiki;
|
||||
public Page_matcher_mgr(Xow_wiki wiki) {this.wiki = wiki;}
|
||||
private final Hash_adp__int hash = new Hash_adp__int();
|
||||
public Page_matcher_wkr Get_by(int ns_id) {
|
||||
Page_matcher_wkr rv = (Page_matcher_wkr)hash.Get_by_or_null(ns_id);
|
||||
if (rv == null) {
|
||||
rv = new Page_matcher_wkr(wiki, ns_id);
|
||||
hash.Add(ns_id, rv);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk__get)) return Get_by(m.ReadInt("v"));
|
||||
else return Gfo_invk_.Rv_unhandled;
|
||||
} private static final String Invk__get = "get";
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.wikis.searchs.bldrs.cmds.adjustments; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.searchs.bldrs.*; import gplx.xowa.addons.wikis.searchs.bldrs.cmds.*;
|
||||
import gplx.core.lists.hashs.*; import gplx.core.primitives.*;
|
||||
import gplx.dbs.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
class Page_matcher_wkr implements Gfo_invk {// NOTE: tries would use less memory, but would be slower, especially for Has*()
|
||||
private final Xow_wiki wiki;
|
||||
private final List_adp rule_list = List_adp_.New();
|
||||
private final Hash_adp__int page_hash = new Hash_adp__int();
|
||||
public Page_matcher_wkr(Xow_wiki wiki, int ns_id) {
|
||||
this.wiki = wiki;
|
||||
this.ns_id = ns_id;
|
||||
}
|
||||
public int Ns_id() {return ns_id;} private final int ns_id;
|
||||
public Page_matcher_itm Get_by_or_null(int page_id) {return (Page_matcher_itm)page_hash.Get_by_or_null(page_id);}
|
||||
public Page_matcher_wkr Load_all() {
|
||||
int len = rule_list.Len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Load((Page_matcher_itm)rule_list.Get_at(i));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
private void Load(Page_matcher_itm itm) {
|
||||
Gfo_log_.Instance.Prog("loading filter", "filter", itm.Page_filter);
|
||||
List_adp page_ids = List_adp_.New();
|
||||
String sql = "", filter_arg = itm.Page_filter;
|
||||
switch (itm.Match_type) {
|
||||
case Page_matcher__match_type.Type__bgn: sql = "SELECT page_id FROM page WHERE page_namespace = ? AND page_title LIKE ?"; filter_arg = filter_arg + "%"; break; // ANSI.Y
|
||||
case Page_matcher__match_type.Type__end: sql = "SELECT page_id FROM page WHERE page_namespace = ? AND page_title LIKE ?"; filter_arg = "%" + filter_arg; break; // ANSI.Y
|
||||
case Page_matcher__match_type.Type__all: sql = "SELECT page_id FROM page WHERE page_namespace = ? AND page_title = ?"; break; // ANSI.Y
|
||||
}
|
||||
Db_stmt stmt = wiki.Data__core_mgr().Db__core().Tbl__page().Conn().Stmt_sql(sql);
|
||||
Db_rdr rdr = stmt.Clear().Crt_int("page_namespace", ns_id).Crt_str("page_title", filter_arg).Exec_select__rls_manual();
|
||||
try {
|
||||
while (rdr.Move_next()) {
|
||||
Int_obj_ref page_id = Int_obj_ref.New(rdr.Read_int("page_id"));
|
||||
page_ids.Add(page_id);
|
||||
page_hash.Add_if_dupe_use_nth(page_id, itm);
|
||||
}
|
||||
} finally {rdr.Rls();}
|
||||
itm.Page_ids = (Int_obj_ref[])page_ids.To_ary_and_clear(Int_obj_ref.class);
|
||||
stmt.Rls();
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk__add)) Add_by_msg(m);
|
||||
else return Gfo_invk_.Rv_unhandled;
|
||||
return this;
|
||||
} private static final String Invk__add = "add";
|
||||
private void Add_by_msg(GfoMsg m) {
|
||||
byte match_type = Page_matcher__match_type.To_tid(m.Args_getAt(0).Val_to_str_or_empty());
|
||||
byte calc_type = Page_matcher__calc_type.To_tid(m.Args_getAt(1).Val_to_str_or_empty());
|
||||
double val = Double_.parse(m.Args_getAt(2).Val_to_str_or_empty());
|
||||
int args_len = m.Args_count();
|
||||
for (int i = 3; i < args_len; ++i) {
|
||||
rule_list.Add(new Page_matcher_itm(match_type, calc_type, val, m.Args_getAt(i).Val_to_str_or_empty()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.wikis.searchs.bldrs.cmds.adjustments; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.searchs.bldrs.*; import gplx.xowa.addons.wikis.searchs.bldrs.cmds.*;
|
||||
class Page_stub implements CompareAble {
|
||||
public Page_stub(int id, boolean is_redirect, int len, int score) {
|
||||
this.Id = id;
|
||||
this.Is_redirect = is_redirect;
|
||||
this.Len = len;
|
||||
this.Score = score;
|
||||
}
|
||||
public final int Id;
|
||||
public final boolean Is_redirect;
|
||||
public final int Len;
|
||||
public final int Score;
|
||||
|
||||
public int compareTo(Object obj) {
|
||||
Page_stub comp = (Page_stub)obj;
|
||||
// sort redirects and small pages to bottom
|
||||
int is_redirect_compare = -Bool_.Compare(Is_redirect, comp.Is_redirect);
|
||||
if (is_redirect_compare == CompareAble_.Same)
|
||||
return Int_.Compare(Len, comp.Len);
|
||||
else
|
||||
return is_redirect_compare;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
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.wikis.searchs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
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.wikis.searchs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.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"
|
||||
;
|
||||
}
|
||||
131
400_xowa/src/gplx/xowa/addons/wikis/searchs/dbs/Srch_db_mgr.java
Normal file
131
400_xowa/src/gplx/xowa/addons/wikis/searchs/dbs/Srch_db_mgr.java
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
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.wikis.searchs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.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 int Tbl__link__get_idx(int ns) {return ns == gplx.xowa.wikis.nss.Xow_ns_.Tid__main ? 0 : tbl__link__ary.length - 1;}
|
||||
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() {
|
||||
Xow_db_mgr db_mgr = wiki.Data__core_mgr();
|
||||
Xowd_core_db_props db_props = db_mgr.Db__core().Db_props();
|
||||
Xow_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) {
|
||||
Xow_db_file db_file = (Xow_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(Xow_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(Xow_db_file_.Tid__search_core);
|
||||
core_data_mgr.Dbs__delete_by_tid(Xow_db_file_.Tid__search_link);
|
||||
}
|
||||
}
|
||||
public void Create_all() {
|
||||
Xow_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
|
||||
Xow_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;
|
||||
Xow_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, Xow_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, Xow_db_mgr db_mgr, int idx, boolean ns_ids_is_main, Xow_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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,11 +15,8 @@ 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.wikis.randoms.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.randoms.*;
|
||||
public class Rndm_core_row {
|
||||
public void Load(int uid, String where_sql, int total, int interval) {this.uid = uid; this.where_sql = where_sql; this.total = total; this.interval = interval;}
|
||||
public int uid;
|
||||
public String where_sql;
|
||||
public int total;
|
||||
public int interval;
|
||||
package gplx.xowa.addons.wikis.searchs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*;
|
||||
import gplx.xowa.wikis.data.*;
|
||||
public class Srch_db_mgr_ {
|
||||
public static final byte Dbtid__search_core = 4, Dbtid__search_link = 16; // SYNC:Xow_db_file_
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
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.wikis.searchs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.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.wikis.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_.Start_by_key("search_upgrade", app.Bldr(), gplx.xowa.bldrs.Xob_bldr.Invk_run);
|
||||
}
|
||||
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
|
||||
;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.wikis.searchs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*;
|
||||
import gplx.dbs.*;
|
||||
public class Srch_link_reg_tbl implements Rls_able {
|
||||
private final String tbl_name; public final Dbmeta_fld_list flds = new Dbmeta_fld_list();
|
||||
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 = "*";
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
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.wikis.searchs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*;
|
||||
public class Srch_link_row {
|
||||
public Srch_link_row(int word_id, int page_id, int link_score) {
|
||||
this.Word_id = word_id;
|
||||
this.Page_id = page_id;
|
||||
this.Link_score = link_score;
|
||||
}
|
||||
public final int Word_id;
|
||||
public final int Page_id;
|
||||
public final int Link_score;
|
||||
public int Trg_db_id;
|
||||
|
||||
public int Db_row_size() {return Db_row_size_fixed;}
|
||||
private static final int Db_row_size_fixed = (3 * 4); // 5 ints
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
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.wikis.searchs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*;
|
||||
import gplx.dbs.*;
|
||||
public class Srch_link_tbl {
|
||||
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 String Tbl_name() {return tbl_name;} private final String tbl_name;
|
||||
public Dbmeta_fld_list Flds() {return flds;} private final Dbmeta_fld_list flds = new Dbmeta_fld_list();
|
||||
public int Id;
|
||||
public void Create_tbl() {conn.Meta_tbl_create(Dbmeta_tbl_itm.New(tbl_name, flds));}
|
||||
public void Create_idx__page_id() {} // TODO_OLD: 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 Srch_link_row New_row(Db_rdr rdr) {
|
||||
return new Srch_link_row(rdr.Read_int(fld_word_id), rdr.Read_int(fld_page_id), rdr.Read_int(fld_link_score));
|
||||
}
|
||||
public void Fill_for_insert(Db_stmt stmt, Srch_link_row row) {
|
||||
stmt.Val_int(fld_word_id, row.Word_id).Val_int(fld_page_id, row.Page_id).Val_int(fld_link_score, row.Link_score);
|
||||
}
|
||||
|
||||
public static final Srch_link_tbl[] Ary_empty = new Srch_link_tbl[0];
|
||||
public static final String Fld_link_score = "link_score";
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
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.wikis.searchs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*;
|
||||
import gplx.dbs.*;
|
||||
public class Srch_temp_tbl {
|
||||
public final String tbl_name = "search_temp";
|
||||
private final Dbmeta_fld_list flds = new Dbmeta_fld_list();
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
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.wikis.searchs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*;
|
||||
public class Srch_word_row {
|
||||
public Srch_word_row(int id, byte[] text, int link_count, int link_count_score, int link_score_min, int link_score_max) {
|
||||
this.Id = id; this.Text = text;
|
||||
this.Link_count = link_count; this.Link_count_score = link_count_score;
|
||||
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_count_score;
|
||||
public final int Link_score_min;
|
||||
public final int Link_score_max;
|
||||
|
||||
public int Db_row_size() {return Db_row_size_fixed + Text.length;}
|
||||
private static final int Db_row_size_fixed = (5 * 4); // 5 ints
|
||||
|
||||
public static final Srch_word_row Empty = new Srch_word_row(-1, Bry_.Empty, 0, 0, 0, 0);
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.wikis.searchs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*;
|
||||
import gplx.dbs.*;
|
||||
public class Srch_word_tbl implements Rls_able {
|
||||
public final String tbl_name;
|
||||
public final Dbmeta_fld_list flds = new Dbmeta_fld_list();
|
||||
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 void Insert_by_itm(Db_stmt stmt, Srch_word_row row) {
|
||||
stmt.Clear()
|
||||
.Val_int(fld_id, row.Id).Val_bry_as_str(fld_text, row.Text).Val_int(fld_link_count, row.Link_count)
|
||||
.Val_int(fld_link_count_score, row.Link_count_score).Val_int(fld_link_score_min, row.Link_score_min).Val_int(fld_link_score_max, row.Link_score_max)
|
||||
.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_count_score = fld_link_count_score == Dbmeta_fld_itm.Key_null ? 0 : rdr.Read_int(fld_link_count_score);
|
||||
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_count_score, 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";
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
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.wikis.searchs.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.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_w_size(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() {}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
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.wikis.searchs.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.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))));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
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.wikis.searchs.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
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.wikis.searchs.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.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_w_size(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;
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
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.wikis.searchs.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.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_w_size(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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
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.wikis.searchs.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.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() {}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
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.wikis.searchs.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.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_();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
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.wikis.searchs.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.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;}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
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.wikis.searchs.searchers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.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.New_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};
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
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.wikis.searchs.searchers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*;
|
||||
import gplx.xowa.addons.wikis.searchs.searchers.rslts.*;
|
||||
import gplx.xowa.addons.wikis.searchs.searchers.crts.*;
|
||||
public class Srch_search_cmd implements Cancelable, Gfo_invk {
|
||||
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();
|
||||
}
|
||||
public 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 Gfo_invk_.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;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
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.wikis.searchs.searchers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*;
|
||||
import gplx.xowa.langs.cases.*;
|
||||
import gplx.xowa.wikis.data.*; import gplx.xowa.wikis.data.tbls.*; import gplx.xowa.addons.wikis.searchs.dbs.*;
|
||||
import gplx.xowa.addons.wikis.searchs.searchers.crts.*; import gplx.xowa.addons.wikis.searchs.searchers.rslts.*; import gplx.dbs.percentiles.*; import gplx.xowa.addons.wikis.searchs.searchers.wkrs.*;
|
||||
import gplx.xowa.addons.wikis.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 Xow_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;
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
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.wikis.searchs.searchers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*;
|
||||
import gplx.xowa.addons.wikis.searchs.searchers.rslts.*; import gplx.xowa.addons.wikis.searchs.searchers.wkrs.*; import gplx.xowa.addons.wikis.searchs.parsers.*; import gplx.xowa.addons.wikis.searchs.searchers.crts.*;
|
||||
import gplx.xowa.addons.wikis.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) { // NOTE: main entry point for search
|
||||
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;
|
||||
if (wiki.App().Mode().Tid_is_http()) // FUTURE: use api async flag instead; WHEN: long polling support
|
||||
cur_cmd.Search();
|
||||
else
|
||||
gplx.core.threads.Thread_adp_.Start_by_key(gplx.xowa.apps.Xoa_thread_.Key_special_suggest, cur_cmd, Srch_search_cmd.Invk__search);
|
||||
}
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
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.wikis.searchs.searchers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*;
|
||||
import gplx.core.btries.*;
|
||||
import gplx.xowa.addons.wikis.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
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.wikis.searchs.searchers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*;
|
||||
import org.junit.*; import gplx.xowa.addons.wikis.searchs.parsers.*; import gplx.xowa.addons.wikis.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));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
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.wikis.searchs.searchers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
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.wikis.searchs.searchers.cbks; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.searchs.searchers.*;
|
||||
import gplx.core.js.*;
|
||||
import gplx.xowa.addons.wikis.searchs.searchers.*; import gplx.xowa.addons.wikis.searchs.searchers.rslts.*;
|
||||
public class Srch_rslt_cbk__suggest_box implements Srch_rslt_cbk, Gfo_invk {
|
||||
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();
|
||||
Gfo_invk_.Invk_by_key(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 Gfo_invk_.Rv_unhandled;
|
||||
return this;
|
||||
}
|
||||
public static final String Invk__notify = "notify";
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
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.wikis.searchs.searchers.cbks; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.searchs.searchers.*;
|
||||
import gplx.gfui.*; import gplx.gfui.controls.standards.*;
|
||||
import gplx.xowa.addons.wikis.searchs.searchers.rslts.*;
|
||||
import gplx.xowa.apps.apis.xowa.addons.searchs.*;
|
||||
public class Srch_rslt_cbk__url_bar implements Srch_rslt_cbk, Gfo_invk {
|
||||
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;
|
||||
}
|
||||
|
||||
Gfo_invk_.Invk_by_key(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 Gfo_invk_.Rv_unhandled;
|
||||
return this;
|
||||
} private static final String Invk__items__update = "items__update";
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
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.wikis.searchs.searchers.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.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));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.wikis.searchs.searchers.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.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);
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
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.wikis.searchs.searchers.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.searchs.searchers.*;
|
||||
import gplx.xowa.addons.wikis.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());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
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.wikis.searchs.searchers.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.searchs.searchers.*;
|
||||
import org.junit.*; import gplx.xowa.addons.wikis.searchs.parsers.*; import gplx.xowa.addons.wikis.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)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
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.wikis.searchs.searchers.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.searchs.searchers.*;
|
||||
import gplx.core.btries.*; import gplx.xowa.langs.cases.*;
|
||||
import gplx.xowa.addons.wikis.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);}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
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.wikis.searchs.searchers.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
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.wikis.searchs.searchers.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.searchs.searchers.*;
|
||||
import org.junit.*; import gplx.xowa.addons.wikis.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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
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.wikis.searchs.searchers.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.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.wikis.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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.wikis.searchs.searchers.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.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;}
|
||||
}
|
||||
@@ -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.wikis.searchs.searchers.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.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];
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
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.wikis.searchs.searchers.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.searchs.searchers.*;
|
||||
public interface Srch_crt_visitor {
|
||||
void Visit(Srch_crt_itm node);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
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.wikis.searchs.searchers.crts.visitors; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.searchs.searchers.*; import gplx.xowa.addons.wikis.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
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.wikis.searchs.searchers.crts.visitors; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.searchs.searchers.*; import gplx.xowa.addons.wikis.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
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.wikis.searchs.searchers.rslts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
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.wikis.searchs.searchers.rslts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.searchs.*; import gplx.xowa.addons.wikis.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();
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user