mirror of
https://github.com/gnosygnu/xowa.git
synced 2026-03-02 03:49:30 +00:00
v2.7.2.1
This commit is contained in:
30
400_xowa/src/gplx/xowa/specials/Xoa_special_mgr.java
Normal file
30
400_xowa/src/gplx/xowa/specials/Xoa_special_mgr.java
Normal file
@@ -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.specials; import gplx.*; import gplx.xowa.*;
|
||||
public class Xoa_special_mgr implements GfoInvkAble {
|
||||
private Ordered_hash hash = Ordered_hash_.new_();
|
||||
public Xoa_special_mgr() {
|
||||
hash.Add(gplx.xowa.xtns.wdatas.specials.Wdata_itemByTitle_cfg.Key, new gplx.xowa.xtns.wdatas.specials.Wdata_itemByTitle_cfg());
|
||||
}
|
||||
public void Add(String key, GfoInvkAble cfg) {hash.Add(key, cfg);}
|
||||
public GfoInvkAble Get_or_null(String key) {return (GfoInvkAble)hash.Get_by(key);}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_get)) return Get_or_null(m.ReadStr("v"));
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
} private static final String Invk_get = "get";
|
||||
}
|
||||
95
400_xowa/src/gplx/xowa/specials/Xows_mgr.java
Normal file
95
400_xowa/src/gplx/xowa/specials/Xows_mgr.java
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials; import gplx.*; import gplx.xowa.*;
|
||||
import gplx.xowa.users.history.*;
|
||||
import gplx.xowa.specials.*;
|
||||
import gplx.xowa.specials.allPages.*; import gplx.xowa.specials.search.*; import gplx.xowa.specials.nearby.*; import gplx.xowa.specials.randoms.*; import gplx.xowa.specials.statistics.*; import gplx.xowa.xtns.translates.*; import gplx.xowa.specials.movePage.*;
|
||||
import gplx.xowa.specials.xowa.system_data.*; import gplx.xowa.specials.xowa.default_tab.*; import gplx.xowa.specials.xowa.popup_history.*; import gplx.xowa.specials.xowa.file_browsers.*; import gplx.xowa.specials.xowa.bookmarks.*; import gplx.xowa.specials.xowa.diags.*;
|
||||
import gplx.xowa.xtns.wdatas.specials.*;
|
||||
import gplx.xowa.users.data.*;
|
||||
public class Xows_mgr {
|
||||
private final Hash_adp_bry hash;
|
||||
public Xows_mgr(Xowe_wiki wiki, Xol_lang lang) {
|
||||
hash = Hash_adp_bry.ci_utf8_(lang.Case_mgr());
|
||||
page_allpages = new Xows_page_allpages(wiki);
|
||||
page_search = new Xows_page__search(wiki);
|
||||
page_random = new Xows_page_random(wiki);
|
||||
Evt_lang_changed(wiki.Lang());
|
||||
}
|
||||
public Xows_page_allpages Page_allpages() {return page_allpages;} private final Xows_page_allpages page_allpages;
|
||||
public Xows_page__search Page_search() {return page_search;} private final Xows_page__search page_search;
|
||||
public Xows_page_random Page_random() {return page_random;} private final Xows_page_random page_random;
|
||||
public Xop_randomRootPage_page Page_randomRootPage() {return page_randomRootPage;} private final Xop_randomRootPage_page page_randomRootPage = new Xop_randomRootPage_page();
|
||||
public Xou_history_html Page_history() {return page_history;} private final Xou_history_html page_history = new Xou_history_html();
|
||||
public Xoud_history_special Page_history2() {return page_history2;} private final Xoud_history_special page_history2 = new Xoud_history_special();
|
||||
public Nearby_mgr Page_nearby() {return page_nearby;} private final Nearby_mgr page_nearby = new Nearby_mgr();
|
||||
public Xop_mylanguage_page Page_mylanguage() {return page_mylanguage;} private final Xop_mylanguage_page page_mylanguage = new Xop_mylanguage_page();
|
||||
public Wdata_itemByTitle_page Page_itemByTitle() {return page_itemByTitle;} private final Wdata_itemByTitle_page page_itemByTitle = new Wdata_itemByTitle_page();
|
||||
public Xop_statistics_page Page_statistics() {return page_statistics;} private final Xop_statistics_page page_statistics = new Xop_statistics_page();
|
||||
public Move_page Page_movePage() {return page_movePage;} private final Move_page page_movePage = new Move_page();
|
||||
public System_data_page Page_system_data() {return page_system_data;} private final System_data_page page_system_data = new System_data_page();
|
||||
public Default_tab_page Page_default_tab() {return page_default_tab;} private final Default_tab_page page_default_tab = new Default_tab_page();
|
||||
public Popup_history_page Page_popup_history() {return page_popup_history;} private final Popup_history_page page_popup_history = new Popup_history_page();
|
||||
public Xosp_fbrow_special Page_file_browser() {return page_file_browser;} private final Xosp_fbrow_special page_file_browser = new Xosp_fbrow_special();
|
||||
public Xows_bmk_page Page_bmk() {return page_bmk;} private final Xows_bmk_page page_bmk = new Xows_bmk_page();
|
||||
public Xows_diag_page Page_diag() {return page_diag;} private final Xows_diag_page page_diag = new Xows_diag_page();
|
||||
public void Evt_lang_changed(Xol_lang lang) {
|
||||
hash.Clear();
|
||||
hash.Add_str_obj(Xows_special_meta_.Key__search , page_search);
|
||||
hash.Add_str_obj(Xows_special_meta_.Key__all_pages , page_allpages);
|
||||
hash.Add_str_obj("prefixindex" , page_allpages);
|
||||
hash.Add_str_obj(Xows_special_meta_.Key__random , page_random);
|
||||
hash.Add_str_obj("random" , page_random);
|
||||
hash.Add_str_obj(Xows_special_meta_.Key__random_root_page , page_randomRootPage);
|
||||
hash.Add_bry_obj(Xou_history_mgr.Ttl_name , page_history);
|
||||
hash.Add_str_obj(Xows_special_meta_.Key__page_history , page_history2);
|
||||
hash.Add_str_obj(Xows_special_meta_.Key__nearby , page_nearby);
|
||||
hash.Add_str_obj(Xows_special_meta_.Key__my_language , page_mylanguage);
|
||||
hash.Add_str_obj(Xows_special_meta_.Key__item_by_title , page_itemByTitle);
|
||||
hash.Add_str_obj(Xows_special_meta_.Key__statistics , page_statistics);
|
||||
hash.Add_str_obj(Xows_special_meta_.Key__move_page , page_movePage);
|
||||
hash.Add_str_obj(Xows_special_meta_.Key__system_data , page_system_data);
|
||||
hash.Add_str_obj(Xows_special_meta_.Key__default_tab , page_default_tab);
|
||||
hash.Add_str_obj(Xows_special_meta_.Key__popup_history , page_popup_history);
|
||||
hash.Add_str_obj(Xows_special_meta_.Key__file_browser , page_file_browser);
|
||||
hash.Add_str_obj(Xows_special_meta_.Key__bookmarks , page_bmk);
|
||||
hash.Add_str_obj(Xows_special_meta_.Key__diag , page_diag);
|
||||
}
|
||||
public void Special_gen(Xowe_wiki wiki, Xoae_page page, Xoa_url url, Xoa_ttl ttl) {
|
||||
int slash_pos = Bry_finder.Find_fwd(ttl.Page_txt_wo_qargs(), Xoa_ttl.Subpage_spr); // check for slash
|
||||
byte[] special_name = slash_pos == Bry_.NotFound
|
||||
? ttl.Base_txt_wo_qarg() // no slash found; use base_txt; ignore qry args and just get page_names; EX: Search/Earth?fulltext=y; Allpages?from=Earth...
|
||||
: Bry_.Mid(ttl.Page_txt_wo_qargs(), 0, slash_pos); // slash found; use root page; EX: Special:ItemByTitle/enwiki/Earth
|
||||
// byte[] special_name = ttl.Base_txt_wo_qarg(); // NOTE: ignore qry args and just get page_names; EX: Search/Earth?fulltext=y; Allpages?from=Earth...
|
||||
Object o = hash.Get_by_bry(special_name);
|
||||
if (o == null) {
|
||||
gplx.xowa.Xol_specials_itm special_itm = wiki.Lang().Specials_mgr().Get_by_alias(special_name);
|
||||
if (special_itm != null)
|
||||
o = hash.Get_by_bry(special_itm.Special());
|
||||
}
|
||||
if (o != null) {
|
||||
Xows_page special = (Xows_page)o;
|
||||
page.Revision_data().Modified_on_(DateAdp_.Now());
|
||||
special.Special_gen(wiki, page, url, ttl);
|
||||
}
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_search)) return page_search;
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
} private static final String Invk_search = "search";
|
||||
}
|
||||
22
400_xowa/src/gplx/xowa/specials/Xows_page.java
Normal file
22
400_xowa/src/gplx/xowa/specials/Xows_page.java
Normal file
@@ -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.specials; import gplx.*; import gplx.xowa.*;
|
||||
public interface Xows_page {
|
||||
Xows_special_meta Special_meta();
|
||||
void Special_gen(Xowe_wiki wiki, Xoae_page page, Xoa_url url, Xoa_ttl ttl);
|
||||
}
|
||||
35
400_xowa/src/gplx/xowa/specials/Xows_special_meta.java
Normal file
35
400_xowa/src/gplx/xowa/specials/Xows_special_meta.java
Normal file
@@ -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.specials; import gplx.*; import gplx.xowa.*;
|
||||
public class Xows_special_meta {
|
||||
public Xows_special_meta(int src, int uid, String key_str) {
|
||||
this.src = src; this.uid = uid; this.key_str = key_str;
|
||||
this.key_bry = Bry_.new_u8(key_str);
|
||||
this.ttl_str = "Special:" + key_str; // canonical name
|
||||
this.ttl_bry = Bry_.new_u8(ttl_str);
|
||||
}
|
||||
public int Src() {return src;} private final int src;
|
||||
public int Uid() {return uid;} private final int uid;
|
||||
public String Key_str() {return key_str;} private final String key_str;
|
||||
public byte[] Key_bry() {return key_bry;} private final byte[] key_bry;
|
||||
public String Ttl_str() {return ttl_str;} private final String ttl_str;
|
||||
public byte[] Ttl_bry() {return ttl_bry;} private final byte[] ttl_bry;
|
||||
public boolean Match_ttl(Xoa_ttl ttl) {
|
||||
return ttl.Ns().Id_special() && Bry_.Eq(ttl.Root_txt(), key_bry);
|
||||
}
|
||||
}
|
||||
75
400_xowa/src/gplx/xowa/specials/Xows_special_meta_.java
Normal file
75
400_xowa/src/gplx/xowa/specials/Xows_special_meta_.java
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials; import gplx.*; import gplx.xowa.*;
|
||||
public class Xows_special_meta_ {
|
||||
public static final int Src__mw = 1, Src__xowa = 2;
|
||||
public static final int
|
||||
Uid__all_pages = 1
|
||||
, Uid__random = 2
|
||||
, Uid__random_root_page = 3
|
||||
, Uid__search = 4
|
||||
, Uid__statistics = 5
|
||||
, Uid__move_page = 6
|
||||
, Uid__my_language = 7
|
||||
, Uid__item_by_title = 8
|
||||
, Uid__default_tab = 9
|
||||
, Uid__file_browser = 10
|
||||
, Uid__popup_history = 11
|
||||
, Uid__system_data = 12
|
||||
, Uid__nearby = 13
|
||||
, Uid__page_history = 14
|
||||
, Uid__bookmarks = 15
|
||||
, Uid__diag = 16
|
||||
;
|
||||
public static final String
|
||||
Key__all_pages = "AllPages"
|
||||
, Key__random = "RandomPage"
|
||||
, Key__random_root_page = "RandomRootPage"
|
||||
, Key__search = "Search"
|
||||
, Key__statistics = "Statistics"
|
||||
, Key__move_page = "MovePage"
|
||||
, Key__my_language = "MyLanguage"
|
||||
, Key__item_by_title = "ItemByTitle"
|
||||
, Key__default_tab = "XowaDefaultTab"
|
||||
, Key__file_browser = "XowaFileBrowser"
|
||||
, Key__popup_history = "XowaPopupHistory"
|
||||
, Key__system_data = "XowaSystemData"
|
||||
, Key__nearby = "Nearby"
|
||||
, Key__page_history = "XowaHistory"
|
||||
, Key__bookmarks = "XowaBookmarks"
|
||||
, Key__diag = "XowaDiag"
|
||||
;
|
||||
public static final Xows_special_meta
|
||||
Itm__all_pages = new Xows_special_meta(Src__mw , Uid__all_pages , Key__all_pages)
|
||||
, Itm__random = new Xows_special_meta(Src__mw , Uid__random , Key__random)
|
||||
, Itm__random_root_page = new Xows_special_meta(Src__mw , Uid__random_root_page , Key__random_root_page)
|
||||
, Itm__search = new Xows_special_meta(Src__mw , Uid__search , Key__search)
|
||||
, Itm__statistics = new Xows_special_meta(Src__mw , Uid__statistics , Key__statistics)
|
||||
, Itm__move_page = new Xows_special_meta(Src__xowa , Uid__move_page , Key__move_page)
|
||||
, Itm__my_language = new Xows_special_meta(Src__xowa , Uid__my_language , Key__my_language)
|
||||
, Itm__item_by_title = new Xows_special_meta(Src__xowa , Uid__item_by_title , Key__item_by_title)
|
||||
, Itm__default_tab = new Xows_special_meta(Src__xowa , Uid__default_tab , Key__default_tab)
|
||||
, Itm__file_browser = new Xows_special_meta(Src__xowa , Uid__file_browser , Key__file_browser)
|
||||
, Itm__popup_history = new Xows_special_meta(Src__xowa , Uid__popup_history , Key__popup_history)
|
||||
, Itm__system_data = new Xows_special_meta(Src__xowa , Uid__system_data , Key__system_data)
|
||||
, Itm__nearby = new Xows_special_meta(Src__xowa , Uid__nearby , Key__nearby)
|
||||
, Itm__page_history = new Xows_special_meta(Src__xowa , Uid__page_history , Key__page_history)
|
||||
, Itm__bookmarks = new Xows_special_meta(Src__xowa , Uid__bookmarks , Key__bookmarks)
|
||||
, Itm__diag = new Xows_special_meta(Src__xowa , Uid__diag , Key__diag)
|
||||
;
|
||||
}
|
||||
196
400_xowa/src/gplx/xowa/specials/allPages/Xows_page_allpages.java
Normal file
196
400_xowa/src/gplx/xowa/specials/allPages/Xows_page_allpages.java
Normal file
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.allPages; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.core.primitives.*;
|
||||
import gplx.xowa.html.*; import gplx.xowa.html.hrefs.*; import gplx.xowa.html.lnkis.*;
|
||||
import gplx.xowa.wikis.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
public class Xows_page_allpages implements GfoInvkAble, Bry_fmtr_arg, Xows_page {
|
||||
public Xows_page_allpages(Xowe_wiki wiki) {
|
||||
this.wiki = wiki;
|
||||
html_itm_fmtr = new Xos_pagelist_html_itm_fmtr(this, wiki);
|
||||
} private Xos_pagelist_html_itm_fmtr html_itm_fmtr;
|
||||
public Xows_special_meta Special_meta() {return Xows_special_meta_.Itm__all_pages;}
|
||||
public Xowe_wiki Wiki() {return wiki;} private Xowe_wiki wiki;
|
||||
public Bry_fmtr Html_all() {return html_all;} Bry_fmtr html_all = Bry_fmtr.new_(String_.Concat_lines_nl
|
||||
( "<table class=\"mw-allpages-table-form\">"
|
||||
, " <tr>"
|
||||
, " <td class=\"mw-allpages-nav\">"
|
||||
, "~{anchor_prv} |"
|
||||
, "~{anchor_nxt}"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
, "</table>"
|
||||
, "<table class=\"mw-allpages-table-chunk\">"
|
||||
, "<tbody>~{grps}"
|
||||
, "</tbody>"
|
||||
, "</table>"
|
||||
, "<hr/>"
|
||||
, "<div class=\"mw-allpages-nav\">"
|
||||
, "~{anchor_prv} |"
|
||||
, "~{anchor_nxt}"
|
||||
, "</div>"
|
||||
), "grps", "anchor_prv", "anchor_nxt");
|
||||
public Bry_fmtr Html_list_grp() {return html_list_grp;} Bry_fmtr html_list_grp = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( ""
|
||||
, " <tr>~{itms}"
|
||||
, " </tr>"
|
||||
), "itms");
|
||||
public Bry_fmtr Html_list_itm_normal() {return html_list_itm_normal;} Bry_fmtr html_list_itm_normal = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( ""
|
||||
, " <td style=\"width:~{itm_pct}%\"><a~{lnki_atr_cls} href=\"~{lnki_href}\" title=\"~{lnki_title}\">~{lnki_text}</a></td>"
|
||||
), "itm_pct", "lnki_href", "lnki_title", "lnki_text", "lnki_atr_cls");
|
||||
public Bry_fmtr Html_list_itm_redirect() {return html_list_itm_redirect;} Bry_fmtr html_list_itm_redirect = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( ""
|
||||
, " <td style=\"width:~{itm_pct}%\"><div class=\"allpagesredirect\"><a href=\"~{lnki_href}\" class=\"mw-redirect\" title=\"~{lnki_title}\">~{lnki_text}</a></div></td>"
|
||||
), "itm_pct", "lnki_href", "lnki_title", "lnki_text");
|
||||
public Bry_fmtr Html_list_end() {return html_list_end;} Bry_fmtr html_list_end = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( "<a href=\"/wiki/Special:AllPages?from=~{arg_from}~{args__rest}\" title=\"Special:AllPages\">~{lbl_text}</a>"
|
||||
), "arg_from", "args__rest", "lbl_text");
|
||||
public int Itms_per_page() {return itms_per_page;} private int itms_per_page = 345;
|
||||
public void Itms_per_page_(int v) {itms_per_page = v; rslt_list_ttls = new Xowd_page_itm[v];}
|
||||
public int Itms_per_grp() {return itms_per_grp;} private int itms_per_grp = 3;
|
||||
public boolean List_include_redirects() {return show_redirects;} private boolean show_redirects = true;
|
||||
public Xowd_page_itm Rslt_prv() {return rslt_prv;} public void Rslt_prv_(Xowd_page_itm v) {rslt_prv = v;} private Xowd_page_itm rslt_prv;
|
||||
public Xowd_page_itm Rslt_nxt() {return rslt_nxt;} public void Rslt_nxt_(Xowd_page_itm v) {rslt_nxt = v;} private Xowd_page_itm rslt_nxt;
|
||||
public int Rslt_list_len() {return rslt_list_len;} public void Rslt_list_len_(int v) {rslt_list_len = v;} private int rslt_list_len;
|
||||
public Xowd_page_itm[] Rslt_list_ttls() {return rslt_list_ttls;} private Xowd_page_itm[] rslt_list_ttls;
|
||||
public void Special_gen(Xowe_wiki wiki, Xoae_page page, Xoa_url url, Xoa_ttl ttl) {
|
||||
wiki.Ctx().Cur_page().Html_data().Display_ttl_(wiki.Msg_mgr().Val_by_id(Xol_msg_itm_.Id_sp_allpages_hdr));
|
||||
url.Page_bry_(Bry_.Add(Bry_.new_a7("Special:"), ttl.Page_txt_wo_qargs())); // HACK: need to re-set Page b/c href_parser does not eliminate qargs; DATE:2013-02-08
|
||||
if (wiki.Domain_tid() == Xow_domain_type_.Tid_home) {wiki.Appe().Usr_dlg().Prog_many(GRP_KEY, "home.invalid", "AllPages not implemented for home wiki"); return;}
|
||||
if (rslt_list_ttls == null) this.Itms_per_page_(itms_per_page);
|
||||
boolean found = Build_data(url, ttl); if (!found) return;
|
||||
Build_html(page);
|
||||
}
|
||||
private static byte[] Get_from(Xoa_url_arg_hash arg_hash, Xowe_wiki wiki, Xoa_url url, Xoa_ttl ttl) {
|
||||
return ttl.Leaf_bgn() == -1
|
||||
? arg_hash.Get_val_bry_or(Bry_arg_from, null)
|
||||
: ttl.Leaf_url()
|
||||
;
|
||||
}
|
||||
public boolean Build_data(Xoa_url url, Xoa_ttl ttl) {
|
||||
init_ns = wiki.Ns_mgr().Ns_main();
|
||||
arg_hash.Load(url);
|
||||
byte[] from_val = Get_from(arg_hash, wiki, url, ttl); if (from_val == null) return false;
|
||||
from_val = Xoa_app_.Utl__encoder_mgr().Id().Decode(from_val);
|
||||
int ns_val = arg_hash.Get_val_int_or(Bry_arg_ns, init_ns.Id()); init_ns = wiki.Ns_mgr().Ids_get_or_null(ns_val);
|
||||
boolean hide_redirects_val = arg_hash.Get_val_int_or(Bry_arg_hideredirects, 0) == 1;
|
||||
for (int i = 0; i < itms_per_page; i++)
|
||||
rslt_list_ttls[i] = null;
|
||||
rslt_list_len = 0;
|
||||
rslt_nxt = rslt_prv = null;
|
||||
Xoa_ttl from_ttl = Xoa_ttl.parse_(wiki, from_val); if (from_ttl == null) return false;
|
||||
if (!from_ttl.Ns().Id_main()) { // ns specified in title
|
||||
init_ns = from_ttl.Ns();
|
||||
arg_hash.Set_val_by_int(Bry_arg_ns, init_ns.Id());
|
||||
arg_hash.Set_val_by_bry(Bry_arg_from, from_ttl.Page_db());
|
||||
arg_hash.Save(url);
|
||||
}
|
||||
Int_obj_ref rslt_len = Int_obj_ref.new_(rslt_list_len);
|
||||
Xowd_page_itm rslt_nxt2 = new Xowd_page_itm();
|
||||
Xowd_page_itm rslt_prv2 = new Xowd_page_itm();
|
||||
int all_pages_min = 0;// no minimum for all pages
|
||||
List_adp rslt_list = List_adp_.new_();
|
||||
wiki.Db_mgr().Load_mgr().Load_ttls_for_all_pages(Cancelable_.Never, rslt_list, rslt_nxt2, rslt_prv2, rslt_len, init_ns, from_ttl.Page_db(), itms_per_page, all_pages_min, itms_per_page, !hide_redirects_val, true);
|
||||
rslt_list_len = rslt_len.Val();
|
||||
for (int i = 0; i < rslt_list_len; i++)
|
||||
rslt_list_ttls[i] = (Xowd_page_itm)rslt_list.Get_at(i);
|
||||
rslt_nxt = rslt_nxt2;
|
||||
rslt_prv = rslt_prv2;
|
||||
return true;
|
||||
} private Xoa_url_arg_hash arg_hash = new Xoa_url_arg_hash();
|
||||
private static final byte[] Bry_arg_from = Bry_.new_a7("from"), Bry_arg_ns = Bry_.new_a7("namespace"), Bry_arg_hideredirects = Bry_.new_a7("hideredirects");
|
||||
public Xow_ns Init_ns() {return init_ns;} private Xow_ns init_ns;
|
||||
public void Build_html(Xoae_page page) {
|
||||
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_m001();
|
||||
byte[] anchor_prv = Build_html_end(tmp_bfr, rslt_prv, false);
|
||||
byte[] anchor_nxt = Build_html_end(tmp_bfr, rslt_nxt, true);
|
||||
html_all.Bld_bfr_many(tmp_bfr, this, anchor_prv, anchor_nxt);
|
||||
page.Data_raw_(tmp_bfr.Xto_bry_and_clear());
|
||||
tmp_bfr.Mkr_rls();
|
||||
page.Html_data().Html_restricted_n_();
|
||||
}
|
||||
byte[] Build_html_end(Bry_bfr bfr, Xowd_page_itm itm, boolean fwd) {
|
||||
Xoa_ttl ttl = Xows_page_allpages.ttl_(wiki, init_ns, itm); if (ttl == null) return Bry_.Empty; // occurs when range is empty; EX: Module:A in simplewikibooks
|
||||
int msg_id = fwd ? Xol_msg_itm_.Id_sp_allpages_fwd : Xol_msg_itm_.Id_sp_allpages_bwd;
|
||||
Xol_msg_itm msg_itm = wiki.Lang().Msg_mgr().Itm_by_id_or_null(msg_id);
|
||||
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_b512().Mkr_rls();
|
||||
byte[] lbl_text = msg_itm.Fmt(tmp_bfr, ttl.Full_txt());
|
||||
byte[] args__rest = arg_hash.Concat(tmp_bfr, Bry_arg_ns, Bry_arg_hideredirects);
|
||||
byte[] arg_from = Xoa_app_.Utl__encoder_mgr().Id().Encode(ttl.Page_txt_wo_qargs());
|
||||
return html_list_end.Bld_bry_many(bfr, arg_from, args__rest, lbl_text);
|
||||
}
|
||||
public static Xoa_ttl ttl_(Xowe_wiki wiki, Xow_ns ns, Xowd_page_itm itm) {
|
||||
byte[] ttl_bry = itm.Ttl_page_db();
|
||||
if (!ns.Id_main()) ttl_bry = Bry_.Add(ns.Name_db_w_colon(), ttl_bry);
|
||||
return Xoa_ttl.parse_(wiki, ttl_bry);
|
||||
}
|
||||
public void XferAry(Bry_bfr bfr, int idx) {
|
||||
int len = rslt_list_ttls.length;
|
||||
html_itm_fmtr.XferAry_bgn();
|
||||
for (int i = 0; i < len; i += itms_per_grp) {
|
||||
html_itm_fmtr.Itm_idx_(i);
|
||||
html_list_grp.Bld_bfr_many(bfr, html_itm_fmtr);
|
||||
}
|
||||
html_itm_fmtr.XferAry_end();
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_html_all_)) html_all.Fmt_(m.ReadBry("v"));
|
||||
else if (ctx.Match(k, Invk_html_list_grp_)) html_list_grp.Fmt_(m.ReadBry("v"));
|
||||
else if (ctx.Match(k, Invk_html_list_itm_normal_)) html_list_itm_normal.Fmt_(m.ReadBry("v"));
|
||||
else if (ctx.Match(k, Invk_html_list_itm_redirect_)) html_list_itm_redirect.Fmt_(m.ReadBry("v"));
|
||||
else if (ctx.Match(k, Invk_itms_per_page_)) Itms_per_page_(m.ReadInt("v"));
|
||||
else if (ctx.Match(k, Invk_itms_per_grp_)) itms_per_grp = m.ReadInt("v");
|
||||
else if (ctx.Match(k, Invk_show_redirects_)) show_redirects = m.ReadYn("v");
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
return this;
|
||||
}
|
||||
public static final String Invk_html_all_ = "html_all_", Invk_html_list_grp_ = "html_list_grp_", Invk_html_list_itm_normal_ = "html_list_itm_normal_", Invk_html_list_itm_redirect_ = "html_list_itm_redirect_"
|
||||
, Invk_itms_per_page_ = "itms_per_page_", Invk_itms_per_grp_ = "itms_per_grp_", Invk_show_redirects_ = "show_redirects_";
|
||||
public static final String GRP_KEY = "xowa.special.allpages";
|
||||
}
|
||||
class Xos_pagelist_html_itm_fmtr implements Bry_fmtr_arg {
|
||||
public Xos_pagelist_html_itm_fmtr(Xows_page_allpages mgr, Xowe_wiki wiki) {
|
||||
this.mgr = mgr; this.wiki = wiki; this.href_parser = wiki.Appe().Href_parser(); this.wiki_key = wiki.Domain_bry();
|
||||
this.itm_normal = mgr.Html_list_itm_normal(); this.itm_redirect = mgr.Html_list_itm_redirect();
|
||||
history_mgr = wiki.Appe().Usere().History_mgr();
|
||||
} private Xows_page_allpages mgr; Xowe_wiki wiki; Xoh_href_parser href_parser; Bry_fmtr itm_normal, itm_redirect; byte[] wiki_key; gplx.xowa.users.history.Xou_history_mgr history_mgr;
|
||||
public void Itm_idx_(int v) {itm_idx = v;} private int itm_idx;
|
||||
public void XferAry_bgn() {
|
||||
itms_per_grp = mgr.Itms_per_grp();
|
||||
ttls = mgr.Rslt_list_ttls();
|
||||
ttls_len = ttls.length;
|
||||
itm_pct = 100 / itms_per_grp;
|
||||
init_ns = mgr.Init_ns();
|
||||
} int itms_per_grp, ttls_len, itm_pct; Xowd_page_itm[] ttls; Xow_ns init_ns;
|
||||
public void XferAry_end() {ttls = null;}
|
||||
public void XferAry(Bry_bfr bfr, int idx) {
|
||||
int itm_end = itm_idx + itms_per_grp;
|
||||
for (int i = itm_idx; i < itm_end; i++) {
|
||||
if (i >= ttls_len) break; // handle odd number of itms; EX: interval=3; items=4; proc gets called on 0 (0-2) and 3 (3-5); ArrayIndex for 4, 5
|
||||
Xowd_page_itm ttl_itm = ttls[i];
|
||||
if (ttl_itm == null) break; // ttl_itm can be null at bgn or end of title list; EX: list=A-Z; count=5; key=Z; itms=X,Y,Z,null,null
|
||||
Xoa_ttl ttl = Xows_page_allpages.ttl_(wiki, init_ns, ttl_itm);
|
||||
byte[] href = href_parser.Build_to_bry(wiki, ttl);
|
||||
byte[] title = Xoh_html_wtr.Ttl_to_title(ttl.Full_txt());
|
||||
byte[] cls = Xoh_lnki_wtr.Lnki_cls_visited(history_mgr, wiki_key, ttl.Page_txt()); // NOTE: must be ttl.Page_txt() in order to match Xou_history_mgr.Add
|
||||
Bry_fmtr fmtr = ttl_itm.Redirected() ? itm_redirect : itm_normal;
|
||||
fmtr.Bld_bfr_many(bfr, itm_pct, href, title, ttl.Full_txt(), cls);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.allPages; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import org.junit.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
public class Xows_page_allpages_tst {
|
||||
@Before public void init() {fxt.Clear();} private Xows_page_allpages_fxt fxt = new Xows_page_allpages_fxt();
|
||||
@Test public void Build_data() {
|
||||
Xow_hive_mgr_fxt.Ttls_create_rng(fxt.Wiki(), 5, 7);
|
||||
fxt.Clear().Init_ttl_leaf("/B1").Expd_prv("A3").Expd_nxt("B6").Expd_ttls("B1", "B2", "B3", "B4", "B5").Test_build_data(); // SpecialPage:AllPages/B1
|
||||
fxt.Clear().Init_arg("from", "B1").Expd_prv("A3").Expd_nxt("B6").Expd_ttls("B1", "B2", "B3", "B4", "B5").Test_build_data(); // single file
|
||||
fxt.Clear().Init_arg("from", "A6").Expd_prv("A1").Expd_nxt("B4").Expd_ttls("A6", "B0", "B1", "B2", "B3").Test_build_data(); // overflow rhs
|
||||
fxt.Clear().Init_arg("from", "E4").Expd_prv("D6").Expd_nxt("E6").Expd_ttls("E4", "E5", "E6", null, null).Test_build_data(); // bounds rhs
|
||||
fxt.Clear().Init_arg("from", "A0").Expd_prv("A0").Expd_nxt("A5").Expd_ttls("A0", "A1", "A2", "A3", "A4").Test_build_data(); // bounds lhs
|
||||
fxt.Clear().Init_arg("from", "B0a").Expd_prv("A3").Expd_nxt("B6").Expd_ttls("B1", "B2", "B3", "B4", "B5").Test_build_data(); // inexact match; B0a matches "hi" value
|
||||
fxt.Clear().Init_arg("from", "B1").Init_arg("hideredirects", "1").Expd_prv("A0").Expd_nxt("C4").Expd_ttls("B2", "B4", "B6", "C0", "C2").Test_build_data(); // hide redirects
|
||||
fxt.Clear().Init_arg("from", "A6").Expd_prv("A0").Expd_nxt("E1").Init_itms_per_page(23).Expd_ttls("A6", "B0", "B1", "B2", "B3", "B4", "B5", "B6", "C0", "C1", "C2", "C3", "C4", "C5", "C6", "D0", "D1", "D2", "D3", "D4", "D5", "D6", "E0").Test_build_data(); // overflow rhs x2
|
||||
}
|
||||
@Test public void Build_html_main() {
|
||||
Xow_hive_mgr_fxt.Ttls_create_rng(fxt.Wiki(), 5, 7);
|
||||
fxt.Clear().Init_arg("from", "B2").Init_itms_per_page(5).Test_build_html(String_.Concat_lines_nl
|
||||
( "<table class=\"mw-allpages-table-form\">"
|
||||
, " <tr>"
|
||||
, " <td class=\"mw-allpages-nav\">"
|
||||
, "<a href=\"/wiki/Special:AllPages?from=A4\" title=\"Special:AllPages\">Previous page (A4)</a> |"
|
||||
, "<a href=\"/wiki/Special:AllPages?from=C0\" title=\"Special:AllPages\">Next page (C0)</a>"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
, "</table>"
|
||||
, "<table class=\"mw-allpages-table-chunk\">"
|
||||
, "<tbody>"
|
||||
, " <tr>"
|
||||
, " <td style=\"width:33%\"><a href=\"/wiki/B2\" title=\"B2\">B2</a></td>"
|
||||
, " <td style=\"width:33%\"><div class=\"allpagesredirect\"><a href=\"/wiki/B3\" class=\"mw-redirect\" title=\"B3\">B3</a></div></td>"
|
||||
, " <td style=\"width:33%\"><a href=\"/wiki/B4\" title=\"B4\">B4</a></td>"
|
||||
, " </tr>"
|
||||
, " <tr>"
|
||||
, " <td style=\"width:33%\"><div class=\"allpagesredirect\"><a href=\"/wiki/B5\" class=\"mw-redirect\" title=\"B5\">B5</a></div></td>"
|
||||
, " <td style=\"width:33%\"><a href=\"/wiki/B6\" title=\"B6\">B6</a></td>"
|
||||
, " </tr>"
|
||||
, "</tbody>"
|
||||
, "</table>"
|
||||
, "<hr/>"
|
||||
, "<div class=\"mw-allpages-nav\">"
|
||||
, "<a href=\"/wiki/Special:AllPages?from=A4\" title=\"Special:AllPages\">Previous page (A4)</a> |"
|
||||
, "<a href=\"/wiki/Special:AllPages?from=C0\" title=\"Special:AllPages\">Next page (C0)</a>"
|
||||
, "</div>"
|
||||
));
|
||||
}
|
||||
@Test public void Build_html_redirect() {
|
||||
Xow_hive_mgr_fxt.Ttls_create_rng(fxt.Wiki(), 1, 7);
|
||||
fxt.Clear().Init_arg("from", "A2").Init_arg("hideredirects", "1").Init_itms_per_page(2).Test_build_html(String_.Concat_lines_nl
|
||||
( "<table class=\"mw-allpages-table-form\">"
|
||||
, " <tr>"
|
||||
, " <td class=\"mw-allpages-nav\">"
|
||||
, "<a href=\"/wiki/Special:AllPages?from=A0&hideredirects=1\" title=\"Special:AllPages\">Previous page (A0)</a> |"
|
||||
, "<a href=\"/wiki/Special:AllPages?from=A6&hideredirects=1\" title=\"Special:AllPages\">Next page (A6)</a>"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
, "</table>"
|
||||
, "<table class=\"mw-allpages-table-chunk\">"
|
||||
, "<tbody>"
|
||||
, " <tr>"
|
||||
, " <td style=\"width:33%\"><a href=\"/wiki/A2\" title=\"A2\">A2</a></td>"
|
||||
, " <td style=\"width:33%\"><a href=\"/wiki/A4\" title=\"A4\">A4</a></td>"
|
||||
, " </tr>"
|
||||
, "</tbody>"
|
||||
, "</table>"
|
||||
, "<hr/>"
|
||||
, "<div class=\"mw-allpages-nav\">"
|
||||
, "<a href=\"/wiki/Special:AllPages?from=A0&hideredirects=1\" title=\"Special:AllPages\">Previous page (A0)</a> |"
|
||||
, "<a href=\"/wiki/Special:AllPages?from=A6&hideredirects=1\" title=\"Special:AllPages\">Next page (A6)</a>"
|
||||
, "</div>"
|
||||
));
|
||||
}
|
||||
@Test public void Build_html_ns() {
|
||||
Xow_hive_mgr_fxt.Ttls_create_rng(fxt.Wiki(), fxt.Wiki().Ns_mgr().Ns_template(), 1, 7);
|
||||
fxt.Clear().Init_arg("from", "A2").Init_arg("namespace", "10").Init_itms_per_page(2).Test_build_html(String_.Concat_lines_nl
|
||||
( "<table class=\"mw-allpages-table-form\">"
|
||||
, " <tr>"
|
||||
, " <td class=\"mw-allpages-nav\">"
|
||||
, "<a href=\"/wiki/Special:AllPages?from=A0&namespace=10\" title=\"Special:AllPages\">Previous page (Template:A0)</a> |"
|
||||
, "<a href=\"/wiki/Special:AllPages?from=A4&namespace=10\" title=\"Special:AllPages\">Next page (Template:A4)</a>"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
, "</table>"
|
||||
, "<table class=\"mw-allpages-table-chunk\">"
|
||||
, "<tbody>"
|
||||
, " <tr>"
|
||||
, " <td style=\"width:33%\"><a href=\"/wiki/Template:A2\" title=\"Template:A2\">Template:A2</a></td>"
|
||||
, " <td style=\"width:33%\"><div class=\"allpagesredirect\"><a href=\"/wiki/Template:A3\" class=\"mw-redirect\" title=\"Template:A3\">Template:A3</a></div></td>"
|
||||
, " </tr>"
|
||||
, "</tbody>"
|
||||
, "</table>"
|
||||
, "<hr/>"
|
||||
, "<div class=\"mw-allpages-nav\">"
|
||||
, "<a href=\"/wiki/Special:AllPages?from=A0&namespace=10\" title=\"Special:AllPages\">Previous page (Template:A0)</a> |"
|
||||
, "<a href=\"/wiki/Special:AllPages?from=A4&namespace=10\" title=\"Special:AllPages\">Next page (Template:A4)</a>"
|
||||
, "</div>"
|
||||
));
|
||||
}
|
||||
@Test public void Misc() {
|
||||
Xow_hive_mgr_fxt.Ttls_create_rng(fxt.Wiki(), fxt.Wiki().Ns_mgr().Ns_template(), 1, 7);
|
||||
fxt.Clear().Init_arg("from", "Template:B1").Expd_arg("from", "B1").Expd_arg("namespace", "10").Test_build_data(); // extract ns from ttl
|
||||
fxt.Clear().Init_arg("from", "Template:B1").Expd_display_ttl("All pages").Expd_address_page("Special:AllPages").Test_special_gen(); // display ttl
|
||||
}
|
||||
}
|
||||
class Xows_page_allpages_fxt {
|
||||
public Xows_page_allpages_fxt Clear() {
|
||||
if (app == null) {
|
||||
app = Xoa_app_fxt.app_();
|
||||
wiki = Xoa_app_fxt.wiki_tst_(app);
|
||||
allpages = wiki.Special_mgr().Page_allpages();
|
||||
GfoInvkAble_.InvkCmd_val(allpages, Xows_page_allpages.Invk_itms_per_page_, 5);
|
||||
}
|
||||
init_ttl_leaf = "";
|
||||
expd_prv = expd_nxt = null;
|
||||
expd_ttls = null;
|
||||
expd_display_ttl = null;
|
||||
return this;
|
||||
} private Xoae_app app;
|
||||
public Xowe_wiki Wiki() {return wiki;} private Xowe_wiki wiki; Xows_page_allpages allpages;
|
||||
public Xows_page_allpages_fxt Init_arg(String key, String val) {init_args.Add(new Gfo_url_arg(Bry_.new_a7(key), Bry_.new_a7(val))); return this;} private List_adp init_args = List_adp_.new_();
|
||||
public Xows_page_allpages_fxt Init_ttl_leaf(String val) {init_ttl_leaf = val; return this;} private String init_ttl_leaf;
|
||||
public Xows_page_allpages_fxt Init_itms_per_page(int v) {init_itms_per_page = v; return this;} private int init_itms_per_page = 5;
|
||||
public Xows_page_allpages_fxt Expd_arg(String key, String val) {expd_args.Add(new Gfo_url_arg(Bry_.new_a7(key), Bry_.new_a7(val))); return this;} private List_adp expd_args = List_adp_.new_();
|
||||
public Xows_page_allpages_fxt Expd_prv(String v) {expd_prv = v; return this;} private String expd_prv;
|
||||
public Xows_page_allpages_fxt Expd_nxt(String v) {expd_nxt = v; return this;} private String expd_nxt;
|
||||
public Xows_page_allpages_fxt Expd_ttls(String... v) {expd_ttls = v; return this;} private String[] expd_ttls;
|
||||
public Xows_page_allpages_fxt Expd_display_ttl(String v) {expd_display_ttl = v; return this;} private String expd_display_ttl;
|
||||
public Xows_page_allpages_fxt Expd_address_page(String v) {expd_address_page = v; return this;} private String expd_address_page;
|
||||
|
||||
public static String Xto_str(Xowe_wiki wiki, Xowd_page_itm v) {
|
||||
if (v == null) return null;
|
||||
Xow_ns ns = wiki.Ns_mgr().Ids_get_or_null(v.Ns_id());
|
||||
String ns_str = ns == null ? "" : String_.new_a7(ns.Name_db_w_colon());
|
||||
return ns_str + String_.new_a7(v.Ttl_page_db());
|
||||
}
|
||||
public static String[] Xto_str_ary(Xowe_wiki wiki, Xowd_page_itm[] ary) {
|
||||
int ary_len = ary.length;
|
||||
String[] rv = new String[ary_len];
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
Xowd_page_itm itm = ary[i];
|
||||
rv[i] = Xto_str(wiki, itm);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static String[] Xto_str_ary(Gfo_url_arg[] ary) {
|
||||
int ary_len = ary.length;
|
||||
String[] rv = new String[ary_len];
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
Gfo_url_arg itm = ary[i];
|
||||
rv[i] = String_.new_u8(itm.Key_bry()) + "=" + String_.new_u8(itm.Val_bry());
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public Xows_page_allpages_fxt Test_special_gen() {
|
||||
Xoa_url_parser parserx = new Xoa_url_parser();
|
||||
parserx.Parse(init_url, Xows_special_meta_.Itm__all_pages.Ttl_bry());
|
||||
Xoa_ttl init_ttl = Make_init_ttl();
|
||||
allpages.Special_gen(wiki, wiki.Ctx().Cur_page(), init_url, init_ttl);
|
||||
if (expd_display_ttl != null) Tfds.Eq(expd_display_ttl, String_.new_u8(wiki.Ctx().Cur_page().Html_data().Display_ttl()));
|
||||
if (expd_address_page != null) Tfds.Eq(expd_address_page, String_.new_u8(init_url.Page_bry()));
|
||||
return this;
|
||||
}
|
||||
public Xows_page_allpages_fxt Test_build_data() {
|
||||
Exec_build();
|
||||
if (expd_ttls != null) Tfds.Eq_ary_str(expd_ttls, Xto_str_ary(wiki, allpages.Rslt_list_ttls()));
|
||||
if (expd_nxt != null) Tfds.Eq(expd_nxt, Xto_str(wiki, allpages.Rslt_nxt()));
|
||||
if (expd_prv != null) Tfds.Eq(expd_prv, Xto_str(wiki, allpages.Rslt_prv()));
|
||||
if (expd_args.Count() > 0) {
|
||||
Gfo_url_arg[] expd_args_ary = (Gfo_url_arg[])expd_args.To_ary(Gfo_url_arg.class);
|
||||
Tfds.Eq_ary_str(Xto_str_ary(init_url.Args()), Xto_str_ary(expd_args_ary));
|
||||
}
|
||||
return this;
|
||||
} private Xoa_url init_url = Xoa_url.blank_();
|
||||
public Xows_page_allpages_fxt Test_build_html(String expd) {
|
||||
Exec_build();
|
||||
allpages.Build_html(wiki.Ctx().Cur_page());
|
||||
Tfds.Eq_str_lines(expd, String_.new_a7(wiki.Ctx().Cur_page().Data_raw()));
|
||||
return this;
|
||||
}
|
||||
private void Exec_build() {
|
||||
if (allpages.Itms_per_page() != init_itms_per_page) allpages.Itms_per_page_(init_itms_per_page);
|
||||
init_url.Args_((Gfo_url_arg[])init_args.To_ary(Gfo_url_arg.class));
|
||||
init_args.Clear();
|
||||
Xoa_ttl init_ttl = Make_init_ttl();
|
||||
allpages.Build_data(init_url, init_ttl);
|
||||
}
|
||||
private Xoa_ttl Make_init_ttl() {return Xoa_ttl.parse_(wiki, Bry_.new_u8(Xows_special_meta_.Itm__all_pages.Ttl_str() + init_ttl_leaf));}
|
||||
}
|
||||
181
400_xowa/src/gplx/xowa/specials/movePage/Move_page.java
Normal file
181
400_xowa/src/gplx/xowa/specials/movePage/Move_page.java
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.movePage; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.core.primitives.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
import gplx.xowa.html.hrefs.*;
|
||||
public class Move_page implements Xows_page {
|
||||
private Move_trg_ns_list_fmtr ns_list_fmtr = new Move_trg_ns_list_fmtr();
|
||||
private Move_url_args args = new Move_url_args();
|
||||
private Xoa_ttl src_ttl;
|
||||
public Xows_special_meta Special_meta() {return Xows_special_meta_.Itm__move_page;}
|
||||
public void Special_gen(Xowe_wiki wiki, Xoae_page page, Xoa_url url, Xoa_ttl ttl) {
|
||||
args.Parse(url);
|
||||
byte[] src_ttl_bry = args.Src_ttl();
|
||||
src_ttl = Xoa_ttl.parse_(wiki, src_ttl_bry);
|
||||
if (args.Submitted()) {
|
||||
Exec_rename(wiki, page);
|
||||
return;
|
||||
}
|
||||
byte[] html = Bld_html(page);
|
||||
page.Html_data().Html_restricted_n_(); // [[Special:]] pages allow all HTML
|
||||
page.Data_raw_(html);
|
||||
}
|
||||
private void Exec_rename(Xowe_wiki wiki, Xoae_page page) {
|
||||
gplx.xowa.dbs.Xodb_save_mgr save_mgr = wiki.Db_mgr().Save_mgr();
|
||||
int trg_ns_id = args.Trg_ns();
|
||||
Xow_ns trg_ns = wiki.Ns_mgr().Ids_get_or_null(trg_ns_id); if (trg_ns == null) throw Exc_.new_("unknown ns", "ns", trg_ns_id);
|
||||
byte[] trg_ttl_bry = args.Trg_ttl();
|
||||
Xoa_ttl trg_ttl = Xoa_ttl.parse_(wiki, trg_ns_id, trg_ttl_bry);
|
||||
Xowd_page_itm src_page = new Xowd_page_itm();
|
||||
wiki.Db_mgr().Load_mgr().Load_by_ttl(src_page, src_ttl.Ns(), src_ttl.Page_db());
|
||||
page.Revision_data().Id_(src_page.Id());
|
||||
page.Revision_data().Modified_on_(src_page.Modified_on());
|
||||
page.Data_raw_(src_page.Text());
|
||||
if (args.Create_redirect()) { // NOTE: not tested; DATE:2014-02-27
|
||||
save_mgr.Data_update(page, Xop_redirect_mgr.Make_redirect_text(trg_ttl.Full_db()));
|
||||
Xowd_page_itm trg_page = new Xowd_page_itm();
|
||||
boolean trg_page_exists = wiki.Db_mgr().Load_mgr().Load_by_ttl(trg_page, trg_ns, trg_ttl_bry);
|
||||
if (trg_page_exists)
|
||||
save_mgr.Data_update(page, page.Data_raw());
|
||||
else
|
||||
save_mgr.Data_create(trg_ttl, page.Data_raw());
|
||||
}
|
||||
else
|
||||
save_mgr.Data_rename(page, trg_ns_id, trg_ttl_bry);
|
||||
wiki.Data_mgr().Redirect(page, trg_ns.Gen_ttl(trg_ttl_bry));
|
||||
}
|
||||
private byte[] Bld_html(Xoae_page page) {
|
||||
Xowe_wiki wiki = page.Wikie(); Xow_msg_mgr msg_mgr = wiki.Msg_mgr();
|
||||
if (src_ttl == null) return Bry_.Empty;
|
||||
ns_list_fmtr.Init_by_page(wiki, page, src_ttl);
|
||||
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_m001();
|
||||
wiki.Parser().Parse_text_to_html(tmp_bfr, page, true, msg_mgr.Val_by_key_obj("movepagetext"));
|
||||
fmtr_all.Bld_bfr_many(tmp_bfr
|
||||
, msg_mgr.Val_by_key_obj("move-page-legend")
|
||||
, Bry_.Add(Xoh_href_parser.Href_wiki_bry, src_ttl.Full_db())
|
||||
, gplx.html.Html_utl.Escape_html_as_bry(src_ttl.Full_txt())
|
||||
, src_ttl.Full_txt()
|
||||
, msg_mgr.Val_by_key_obj("newtitle")
|
||||
, ns_list_fmtr
|
||||
, args.Trg_ttl()
|
||||
, msg_mgr.Val_by_key_obj("move-leave-redirect")
|
||||
, msg_mgr.Val_by_key_obj("movepagebtn")
|
||||
);
|
||||
return tmp_bfr.To_bry_and_rls();
|
||||
}
|
||||
private Bry_fmtr fmtr_all = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( "<form action='/wiki/Special:MovePage' id='movepage'>"
|
||||
, " <fieldset>"
|
||||
, " <legend>~{move-page-legend}</legend>"
|
||||
, " <table id='mw-movepage-table'>"
|
||||
, " <tr>"
|
||||
, " <td class='mw-label'>Move page:</td>"
|
||||
, " <td class='mw-input'>"
|
||||
, " <strong><a href='~{src_href}' title='~{src_title}'>~{src_text}</a></strong>"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
, " <tr>"
|
||||
, " <td class='mw-label'>"
|
||||
, " <label for='wpNewTitleMain'>~{newtitle}</label>"
|
||||
, " </td>"
|
||||
, " <td class='mw-input'>"
|
||||
, " <select id='wpNewTitleNs' name='wpNewTitleNs'>~{trg_ns_list}"
|
||||
, " </select>"
|
||||
, " <input name='wpNewTitleMain' size='60' value='~{trg_title}' type='text' id='wpNewTitleMain' maxlength='255' />"
|
||||
, " <input type='hidden' value='~{src_title}' name='wpOldTitle' />"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
, "<!-- <tr>"
|
||||
, " <td></td>"
|
||||
, " <td class='mw-input'>"
|
||||
, " <input name='wpLeaveRedirect' type='checkbox' value='1' checked='checked' id='wpLeaveRedirect' /> <label for='wpLeaveRedirect'>~{move-leave-redirect}</label>"
|
||||
, " </td>"
|
||||
, " </tr> -->"
|
||||
, " <tr>"
|
||||
, " <td> </td>"
|
||||
, " <td class='mw-submit'>"
|
||||
, " <input type='submit' value='~{movepagebtn}' name='wpMove' />"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
, " </table>"
|
||||
, " </fieldset>"
|
||||
, "</form>"
|
||||
), "move-page-legend", "src_href", "src_title", "src_text", "newtitle", "trg_ns_list", "trg_title", "move-leave-redirect", "movepagebtn");
|
||||
}
|
||||
class Move_trg_ns_list_fmtr implements Bry_fmtr_arg {
|
||||
private Xowe_wiki wiki; private Xoa_ttl ttl;
|
||||
public void Init_by_page(Xowe_wiki wiki, Xoae_page page, Xoa_ttl ttl) {
|
||||
this.wiki = wiki;
|
||||
this.ttl = ttl;
|
||||
}
|
||||
public void XferAry(Bry_bfr bfr, int idx) {
|
||||
Xow_ns_mgr ns_mgr = wiki.Ns_mgr();
|
||||
int ns_len = ns_mgr.Ids_len();
|
||||
for (int i = 0; i < ns_len; i++) {
|
||||
Xow_ns ns = ns_mgr.Ids_get_at(i);
|
||||
if (ns.Is_meta()) continue; // ignore [[Special:]] and [[Media:]]
|
||||
byte[] bry_selected = ttl.Ns().Id() == ns.Id() ? Bry_selected : Bry_.Empty;
|
||||
fmtr.Bld_bfr_many(bfr, ns.Id(), bry_selected, ns.Name_ui());
|
||||
}
|
||||
}
|
||||
private static final byte[] Bry_selected = Bry_.new_a7(" selected=''");
|
||||
private Bry_fmtr fmtr = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( ""
|
||||
, " <option value='~{ns_id}' ~{ns_selected}>~{ns_name}</option>"
|
||||
), "ns_id", "ns_selected", "ns_name");
|
||||
}
|
||||
class Move_url_args {
|
||||
public boolean Submitted() {return submitted;} private boolean submitted;
|
||||
public byte[] Src_ttl() {return src_ttl;} private byte[] src_ttl;
|
||||
public byte[] Trg_ttl() {return trg_ttl;} private byte[] trg_ttl;
|
||||
public int Trg_ns() {return trg_ns;} private int trg_ns;
|
||||
public boolean Create_redirect() {return create_redirect;} private boolean create_redirect;
|
||||
public void Parse(Xoa_url url) {
|
||||
this.Clear();
|
||||
Gfo_url_arg[] args = url.Args();
|
||||
int args_len = args.length;
|
||||
for (int i = 0; i < args_len; i++) {
|
||||
Gfo_url_arg arg = args[i];
|
||||
Object tid_obj = arg_keys.Get_by(arg.Key_bry());
|
||||
byte[] val_bry = arg.Val_bry();
|
||||
if (tid_obj != null) {
|
||||
switch (((Byte_obj_val)tid_obj).Val()) {
|
||||
case Key_submitted: submitted = true; break; // wpMove will only be in query_args if move button is pressed
|
||||
case Key_src_ttl: src_ttl = val_bry; break;
|
||||
case Key_trg_ns: trg_ns = Bry_.Xto_int_or_fail(val_bry); break;
|
||||
case Key_trg_ttl: trg_ttl = val_bry; break;
|
||||
case Key_create_redirect: create_redirect = Bry_.Xto_bool_by_int_or_fail(val_bry); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private void Clear() {
|
||||
submitted = false;
|
||||
src_ttl = trg_ttl = null;
|
||||
trg_ns = Int_.MinValue;
|
||||
create_redirect = false;
|
||||
}
|
||||
private static final byte Key_submitted = 1, Key_src_ttl = 2, Key_trg_ns = 3, Key_trg_ttl = 4, Key_create_redirect = 5;
|
||||
private static final Hash_adp_bry arg_keys = Hash_adp_bry.ci_ascii_()
|
||||
.Add_str_byte("wpMove" , Key_submitted)
|
||||
.Add_str_byte("wpOldTitle" , Key_src_ttl)
|
||||
.Add_str_byte("wpNewTitleNs" , Key_trg_ns)
|
||||
.Add_str_byte("wpNewTitleMain" , Key_trg_ttl)
|
||||
.Add_str_byte("wpLeaveRedirect" , Key_create_redirect)
|
||||
;
|
||||
}
|
||||
196
400_xowa/src/gplx/xowa/specials/nearby/Nearby_mgr.java
Normal file
196
400_xowa/src/gplx/xowa/specials/nearby/Nearby_mgr.java
Normal file
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.nearby; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
public class Nearby_mgr implements Xows_page {
|
||||
Xowe_wiki wiki; byte[] trg;
|
||||
private Hash_adp_bry excluded = Hash_adp_bry.ci_ascii_();
|
||||
private Hash_adp_bry visited = Hash_adp_bry.ci_ascii_();
|
||||
List_adp trail = List_adp_.new_();
|
||||
List_adp results = List_adp_.new_();
|
||||
int results_cur = 0;
|
||||
// int depth_max = 5;
|
||||
// int pages_count = 0;
|
||||
Bry_bfr tmp_bfr = Bry_bfr.new_();
|
||||
public int Results_max() {return results_max;} public Nearby_mgr Results_max_(int v) {results_max = v; return this;} private int results_max = 1;
|
||||
public Xows_special_meta Special_meta() {return Xows_special_meta_.Itm__nearby;}
|
||||
public void Special_gen(Xowe_wiki wiki, Xoae_page page, Xoa_url url, Xoa_ttl ttl) {
|
||||
page.Data_raw_(Bld_html(wiki));
|
||||
page.Html_data().Html_restricted_n_(); // [[Special:]] pages allow all HTML
|
||||
// wiki.ParsePage(page, false); // do not clear else previous Search_text will be lost
|
||||
}
|
||||
byte[] Bld_html(Xowe_wiki wiki) {
|
||||
form_fmtr.Bld_bfr_many(tmp_bfr);
|
||||
List_adp list = Find_from_to(wiki, Bry_.new_a7("Earth"), Bry_.new_a7("Atom"), excluded);
|
||||
tmp_bfr.Add_str_a7("<table>");
|
||||
int len = list.Count();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Nearby_rslt rslt = (Nearby_rslt)list.Get_at(i);
|
||||
tmp_bfr.Add_str_a7("<tr>");
|
||||
int cell_len = rslt.Len();
|
||||
for (int j = 0; j < cell_len; j++) {
|
||||
Xoa_ttl ttl = (Xoa_ttl)rslt.Get_at(j);
|
||||
tmp_bfr.Add_str_a7("<td>[[");
|
||||
tmp_bfr.Add(ttl.Page_db());
|
||||
tmp_bfr.Add_str_a7("]]</td>");
|
||||
}
|
||||
tmp_bfr.Add_str_a7("</tr>");
|
||||
}
|
||||
tmp_bfr.Add_str_a7("</table>");
|
||||
return tmp_bfr.Xto_bry_and_clear();
|
||||
}
|
||||
Bry_fmtr form_fmtr = Bry_fmtr.new_(String_.Concat_lines_nl
|
||||
( "<form id='xowa_nearby_form' action='/wiki/Special:XowaNearby'>"
|
||||
, "<table>"
|
||||
, " <tr><td>From:</td><td><input name='xowa_bgn' value='Earth' /></td></tr>"
|
||||
, " <tr><td>To: </td><td><input name='xowa_end' value='Atom' /></td></tr>"
|
||||
, " <tr><td>Max: </td><td><input name='xowa_max' value='1' /></td></tr>"
|
||||
, " <tr><td>Skip:</td><td><input name='xowa_skip' value='' /></td></tr>"
|
||||
, " <tr><td/><td align='right'><input type='submit' value='go' /></td></tr>"
|
||||
, "</table>"
|
||||
, "</form>"
|
||||
));
|
||||
Xoa_ttl trg_ttl;
|
||||
Ordered_hash src_pool = Ordered_hash_.new_bry_();
|
||||
public List_adp Find_from_to(Xowe_wiki wiki, byte[] src_bry, byte[] trg_bry, Hash_adp_bry excluded) {
|
||||
this.wiki = wiki; this.excluded = excluded;
|
||||
Xoa_ttl src_ttl = Xoa_ttl.parse_(wiki, src_bry); if (src_ttl == null) return List_adp_.Noop;
|
||||
trg_ttl = Xoa_ttl.parse_(wiki, trg_bry); if (trg_ttl == null) return List_adp_.Noop;
|
||||
trg = trg_ttl.Page_db();
|
||||
trail.Clear();
|
||||
results.Clear();
|
||||
results_cur = 0;
|
||||
// pages_count = 0;
|
||||
visited.Clear();
|
||||
src_pool.Clear();
|
||||
src_pool.Add(src_ttl.Page_db(), new Nearby_itmx(trail, src_ttl));
|
||||
Examine_page(src_pool);
|
||||
return results;
|
||||
}
|
||||
private void Examine_page(Ordered_hash src_pool){
|
||||
int len = src_pool.Count();
|
||||
Ordered_hash next_pool = Ordered_hash_.new_bry_();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Nearby_itmx itmx = (Nearby_itmx)src_pool.Get_at(i);
|
||||
Xoa_ttl ttl = itmx.Ttl();
|
||||
byte[] ttl_bry = ttl.Page_db();
|
||||
if (excluded.Has(ttl_bry)) continue;
|
||||
if (visited.Has(ttl_bry)) continue;
|
||||
visited.Add_bry_bry(ttl_bry);
|
||||
Xoae_page page = wiki.Data_mgr().Get_page(ttl, false);
|
||||
if (page.Missing()) continue;
|
||||
wiki.ParsePage(page, true);
|
||||
Ordered_hash lnkis = Ordered_hash_.new_bry_();
|
||||
Collect_lnkis(lnkis, page.Root());
|
||||
if (lnkis.Has(trg)) {
|
||||
++results_cur;
|
||||
results.Add(new Nearby_rslt(itmx.Trail(), trg_ttl));
|
||||
if (results_cur == results_max) return;
|
||||
}
|
||||
int lnkis_len = lnkis.Count();
|
||||
for (int j = 0; j < lnkis_len; j++) {
|
||||
Xoa_ttl lnki_ttl = (Xoa_ttl)lnkis.Get_at(j);
|
||||
if (next_pool.Has(lnki_ttl.Page_db())) continue;
|
||||
Nearby_itmx next_itmx = new Nearby_itmx(itmx.Trail(), lnki_ttl);
|
||||
next_pool.Add(lnki_ttl.Page_db(), next_itmx);
|
||||
}
|
||||
}
|
||||
if (next_pool.Count() > 0)
|
||||
Examine_page(next_pool);
|
||||
// ++pages_count;
|
||||
// wiki.ParsePage(page, true);
|
||||
// Ordered_hash lnkis = Ordered_hash_.new_bry_();
|
||||
// int len = lnkis.Count();
|
||||
// for (int i = 0; i < len; i++) {
|
||||
// Xoa_ttl lnki_ttl = (Xoa_ttl)lnkis.Get_at(i);
|
||||
// if (!lnki_ttl.Ns().Id_main()) continue;
|
||||
// if (Bry_.Eq(lnki_ttl.Page_db(), trg)) continue; // skip trg page
|
||||
// trail.Add(lnki_ttl);
|
||||
// Examine_page(wiki, lnki_ttl, trail);
|
||||
// List_adp_.DelAt_last(trail);
|
||||
// if (results_cur == results_max) return;
|
||||
// }
|
||||
}
|
||||
// private void Examine_page(Xowe_wiki wiki, Xoa_ttl ttl, List_adp trail){
|
||||
// byte[] ttl_bry = ttl.Page_db();
|
||||
// if (excluded.Has(ttl_bry)) return;
|
||||
// if (visited.Has(ttl_bry)) return;
|
||||
// visited.Add_bry_bry(ttl_bry);
|
||||
// Xoae_page page = wiki.Data_mgr().Get_page(ttl, false);
|
||||
// if (page.Missing()) return;
|
||||
// ++pages_count;
|
||||
// wiki.ParsePage(page, true);
|
||||
// Ordered_hash lnkis = Ordered_hash_.new_bry_();
|
||||
// Collect_lnkis(lnkis, page.Root());
|
||||
// if (lnkis.Has(trg)) {
|
||||
// ++results_cur;
|
||||
// results.Add(new Nearby_rslt(trail, trg_ttl));
|
||||
// if (results_cur == results_max) return;
|
||||
// }
|
||||
// int len = lnkis.Count();
|
||||
// for (int i = 0; i < len; i++) {
|
||||
// Xoa_ttl lnki_ttl = (Xoa_ttl)lnkis.Get_at(i);
|
||||
// if (!lnki_ttl.Ns().Id_main()) continue;
|
||||
// if (Bry_.Eq(lnki_ttl.Page_db(), trg)) continue; // skip trg page
|
||||
// trail.Add(lnki_ttl);
|
||||
// Examine_page(wiki, lnki_ttl, trail);
|
||||
// List_adp_.DelAt_last(trail);
|
||||
// if (results_cur == results_max) return;
|
||||
// }
|
||||
// }
|
||||
private void Collect_lnkis(Ordered_hash lnkis, Xop_tkn_itm tkn) {
|
||||
if (tkn.Tkn_tid() == Xop_tkn_itm_.Tid_lnki) {
|
||||
Xop_lnki_tkn lnki_tkn = (Xop_lnki_tkn)tkn;
|
||||
Xoa_ttl lnki_ttl = lnki_tkn.Ttl();
|
||||
if (!lnkis.Has(lnki_ttl.Page_db()))
|
||||
lnkis.Add(lnki_ttl.Page_db(), lnki_ttl);
|
||||
}
|
||||
else {
|
||||
int len = tkn.Subs_len();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Xop_tkn_itm sub = tkn.Subs_get(i);
|
||||
Collect_lnkis(lnkis, sub);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
class Nearby_rslt {
|
||||
public Nearby_rslt(List_adp trail, Xoa_ttl trg_ttl) {
|
||||
int len = trail.Count();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Xoa_ttl ttl = (Xoa_ttl)trail.Get_at(i);
|
||||
list.Add(ttl);
|
||||
}
|
||||
list.Add(trg_ttl);
|
||||
}
|
||||
public int Len() {return list.Count();}
|
||||
public Xoa_ttl Get_at(int i) {return (Xoa_ttl)list.Get_at(i);}
|
||||
List_adp list = List_adp_.new_();
|
||||
}
|
||||
class Nearby_itmx {
|
||||
public Nearby_itmx(List_adp v, Xoa_ttl ttl) {
|
||||
int len = v.Count();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Xoa_ttl v_ttl = (Xoa_ttl)v.Get_at(i);
|
||||
trail.Add(v_ttl);
|
||||
}
|
||||
trail.Add(ttl);
|
||||
this.ttl = ttl;
|
||||
}
|
||||
public Xoa_ttl Ttl() {return ttl;} private Xoa_ttl ttl;
|
||||
public List_adp Trail() {return trail;} List_adp trail = List_adp_.new_();
|
||||
}
|
||||
77
400_xowa/src/gplx/xowa/specials/nearby/Nearby_mgr_tst.java
Normal file
77
400_xowa/src/gplx/xowa/specials/nearby/Nearby_mgr_tst.java
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.nearby; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import org.junit.*;
|
||||
public class Nearby_mgr_tst {
|
||||
@Before public void init() {fxt.Clear();} Nearby_mgr_fxt fxt = new Nearby_mgr_fxt();
|
||||
@Test public void Basic() {
|
||||
fxt.Init_page("A", "[[B]]");
|
||||
fxt.Test_find("A", "B", "A|B");
|
||||
}
|
||||
@Test public void Shortest() {
|
||||
fxt.Init_page("A", "[[B]]");
|
||||
fxt.Init_page("B", "[[C]] [[D]]");
|
||||
fxt.Init_page("C", "[[D]]");
|
||||
fxt.Test_find("A", "D", "A|B|D");
|
||||
fxt.Init_results_max(2).Test_find("A", "D", "A|B|D", "A|B|C|D");
|
||||
}
|
||||
@Test public void Circular() {
|
||||
fxt.Init_page("A", "[[B]]");
|
||||
fxt.Init_page("B", "[[C]]");
|
||||
fxt.Init_page("C", "[[A]]");
|
||||
fxt.Test_find("A", "D", "");
|
||||
}
|
||||
@Test public void Page_doesnt_exist() {
|
||||
fxt.Init_page("A", "[[B]]");
|
||||
fxt.Test_find("A", "C", "");
|
||||
}
|
||||
}
|
||||
class Nearby_mgr_fxt {
|
||||
public Nearby_mgr_fxt Clear() {
|
||||
if (fxt == null) {
|
||||
fxt = new Xop_fxt();
|
||||
nearby_mgr = new Nearby_mgr();
|
||||
excluded = Hash_adp_bry.ci_ascii_();
|
||||
tmp_bfr = Bry_bfr.new_();
|
||||
}
|
||||
fxt.Reset();
|
||||
Io_mgr.I.InitEngine_mem();
|
||||
nearby_mgr.Results_max_(1);
|
||||
return this;
|
||||
} private Xop_fxt fxt; Nearby_mgr nearby_mgr; Hash_adp_bry excluded; Bry_bfr tmp_bfr;
|
||||
public void Init_page(String ttl, String text) {fxt.Init_page_create(ttl, text);}
|
||||
public Nearby_mgr_fxt Init_results_max(int v) {nearby_mgr.Results_max_(v); return this;}
|
||||
public void Test_find(String src, String trg, String... expd) {
|
||||
List_adp actl = nearby_mgr.Find_from_to(fxt.Wiki(), Bry_.new_a7(src), Bry_.new_a7(trg), excluded);
|
||||
Tfds.Eq_ary(String_.SplitLines_nl(Xto_str(actl)), expd);
|
||||
}
|
||||
String Xto_str(List_adp list) {
|
||||
int len = list.Count();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Nearby_rslt rslt = (Nearby_rslt)list.Get_at(i);
|
||||
int ttls = rslt.Len();
|
||||
if (i != 0) tmp_bfr.Add_byte_nl();
|
||||
for (int j = 0; j < ttls; j++) {
|
||||
Xoa_ttl ttl = rslt.Get_at(j);
|
||||
if (j != 0) tmp_bfr.Add_byte(Byte_ascii.Pipe);
|
||||
tmp_bfr.Add(ttl.Page_db());
|
||||
}
|
||||
}
|
||||
return tmp_bfr.Xto_str_and_clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.randoms; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
public class Xop_randomRootPage_page implements Xows_page {
|
||||
public Xows_special_meta Special_meta() {return Xows_special_meta_.Itm__random_root_page;}
|
||||
public void Special_gen(Xowe_wiki wiki, Xoae_page page, Xoa_url url, Xoa_ttl ttl) {
|
||||
Xow_ns ns = wiki.Ns_mgr().Names_get_or_main(ttl.Rest_txt());
|
||||
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));
|
||||
}
|
||||
}
|
||||
@@ -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.specials.randoms; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import org.junit.*;
|
||||
public class Xop_randomRootPage_page_tst {
|
||||
@Before public void init() {fxt.Clear();} private Xop_randomRootPage_page_fxt fxt = new Xop_randomRootPage_page_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");
|
||||
}
|
||||
@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 Xop_randomRootPage_page_fxt {
|
||||
public void Clear() {
|
||||
parser_fxt = new Xop_fxt();
|
||||
parser_fxt.Reset();
|
||||
wiki = parser_fxt.Wiki();
|
||||
special_page = wiki.Special_mgr().Page_randomRootPage();
|
||||
} private Xop_fxt parser_fxt; private Xop_randomRootPage_page special_page; private Xowe_wiki wiki;
|
||||
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, Xows_page special_page, String special_url) {
|
||||
Xoae_page page = wiki.Ctx().Cur_page();
|
||||
Xoa_url url = wiki.Appe().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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.randoms; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
public class Xows_page_random implements Xows_page {
|
||||
public Xows_page_random(Xowe_wiki wiki) {}
|
||||
public Xows_special_meta Special_meta() {return Xows_special_meta_.Itm__random;}
|
||||
public void Special_gen(Xowe_wiki wiki, Xoae_page page, Xoa_url url, Xoa_ttl ttl) {
|
||||
Xow_ns ns = wiki.Ns_mgr().Names_get_or_main(ttl.Rest_txt());
|
||||
byte[] random_ttl_bry = wiki.Db_mgr().Load_mgr().Find_random_ttl(ns);
|
||||
wiki.Data_mgr().Redirect(page, ns.Gen_ttl(random_ttl_bry));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.core.primitives.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
class Xog_search_suggest_cmd implements GfoInvkAble, Cancelable {
|
||||
private Xowe_wiki wiki; private byte[] search_bry; private Xosrh_page_mgr searcher; private int max_results, all_pages_extend, all_pages_min;
|
||||
public Xog_search_suggest_cmd(Xoae_app app, Xog_search_suggest_mgr mgr) {
|
||||
this.app = app; this.mgr = mgr;
|
||||
} private Xoae_app app; Xog_search_suggest_mgr mgr; Bry_bfr tmp_bfr = Bry_bfr.reset_(255); List_adp rslts_1 = List_adp_.new_(), rslts_2 = List_adp_.new_();
|
||||
public void Init(Xowe_wiki wiki, byte[] search_bry, int max_results, byte search_mode, int all_pages_extend, int all_pages_min) {
|
||||
this.wiki = wiki; this.search_bry = search_bry; this.max_results = max_results;
|
||||
this.search_mode = search_mode; this.all_pages_extend = all_pages_extend; this.all_pages_min = all_pages_min;
|
||||
searcher = new Xosrh_page_mgr();
|
||||
}
|
||||
private byte search_mode;
|
||||
public byte[] Search_bry() {return search_bry;}
|
||||
public boolean Canceled() {return canceled;}
|
||||
public void Cancel() {this.canceled = true;} private boolean canceled;
|
||||
public void Cancel_reset() {this.canceled = false;}
|
||||
public boolean Working() {return working;} public void Working_(boolean v) {working = v;} private boolean working;
|
||||
public List_adp Results() {return rslts_2;}
|
||||
public void Search() {
|
||||
try { // NOTE: must handle any errors in async mode
|
||||
canceled = false;
|
||||
working = true;
|
||||
boolean pass = false;
|
||||
switch (search_mode) {
|
||||
case Xog_search_suggest_mgr.Tid_search_mode_all_pages_v2: pass = Search_by_all_pages_v2(); break;
|
||||
case Xog_search_suggest_mgr.Tid_search_mode_all_pages_v1: pass = Search_by_all_pages_v1(); break;
|
||||
case Xog_search_suggest_mgr.Tid_search_mode_search: pass = Search_by_search(); break;
|
||||
}
|
||||
if (!pass) return;
|
||||
GfoInvkAble_.InvkCmd(app.Gui_mgr().Kit().New_cmd_sync(mgr), Xog_search_suggest_mgr.Invk_notify);
|
||||
working = false;
|
||||
}
|
||||
catch(Exception e) {
|
||||
app.Usr_dlg().Prog_many("", "", "error during search: ~{0}", Err_.Message_gplx_brief(e));
|
||||
}
|
||||
}
|
||||
private boolean Search_by_all_pages_v2() {
|
||||
rslts_2.Clear();
|
||||
Xoa_ttl search_ttl = Xoa_ttl.parse_(wiki, search_bry); if (search_ttl == null) return false;
|
||||
byte[] search_ttl_bry = search_ttl.Page_db();
|
||||
wiki.Db_mgr().Load_mgr().Load_ttls_for_search_suggest(this, rslts_2, search_ttl.Ns(), search_ttl_bry, max_results, all_pages_min, all_pages_extend, true, false);
|
||||
return true;
|
||||
}
|
||||
private boolean Search_by_all_pages_v1() {
|
||||
rslts_2.Clear();
|
||||
Xowd_page_itm rslt_nxt = new Xowd_page_itm();
|
||||
Xowd_page_itm rslt_prv = new Xowd_page_itm();
|
||||
Xoa_ttl search_ttl = Xoa_ttl.parse_(wiki, search_bry); if (search_ttl == null) return false;
|
||||
byte[] search_ttl_bry = search_ttl.Page_db();
|
||||
List_adp page_list = List_adp_.new_();
|
||||
wiki.Db_mgr().Load_mgr().Load_ttls_for_all_pages(this, page_list, rslt_nxt, rslt_prv, Int_obj_ref.zero_(), wiki.Ns_mgr().Ns_main(), search_ttl_bry, max_results, all_pages_min, all_pages_extend, true, false);
|
||||
Xowd_page_itm[] page_ary = (Xowd_page_itm[])page_list.To_ary_and_clear(Xowd_page_itm.class);
|
||||
int idx = 0, page_ary_len = page_ary.length;
|
||||
for (int i = 0; i < page_ary_len; i++) {
|
||||
Xowd_page_itm page = page_ary[i];
|
||||
if (page != null) {
|
||||
if (!Bry_.Has_at_bgn(page.Ttl_page_db(), search_ttl_bry)) continue; // look-ahead may return other titles that don't begin with search; ignore
|
||||
if (page.Text_len() > all_pages_min) {
|
||||
rslts_2.Add(page);
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
if (idx == max_results) break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private boolean Search_by_search() {
|
||||
Xosrh_rslt_grp rv = searcher.Itms_per_page_(max_results).Search(tmp_bfr, wiki, search_bry, 0, searcher, this);
|
||||
if (canceled) {working = false; return false;}
|
||||
rslts_1.Clear();
|
||||
int len = rv.Itms_len();
|
||||
for (int i = 0; i < len; i++)
|
||||
rslts_1.Add(rv.Itms_get_at(i));
|
||||
if (canceled) {working = false; return false;}
|
||||
rslts_1.Sort_by(Xowd_page_itm_sorter.EnyLenDsc);
|
||||
if (canceled) {working = false; return false;}
|
||||
if (len > max_results) len = max_results;
|
||||
rslts_2.Clear();
|
||||
for (int i = 0; i < len; i++)
|
||||
rslts_2.Add(rslts_1.Get_at(i));
|
||||
if (canceled) {working = false; return false;}
|
||||
rslts_2.Sort_by(Xowd_page_itm_sorter.IdAsc);
|
||||
wiki.Db_mgr().Load_mgr().Load_by_ids(this, rslts_2, 0, len);
|
||||
rslts_2.Sort_by(Xowd_page_itm_sorter.TitleAsc);
|
||||
if (canceled) {working = false; return false;}
|
||||
return true;
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_search)) Search();
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
return this;
|
||||
} public static final String Invk_search = "search";
|
||||
}
|
||||
@@ -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.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.gfui.*; import gplx.core.threads.*; import gplx.xowa.gui.*; import gplx.xowa.gui.views.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
import gplx.core.js.*;
|
||||
public class Xog_search_suggest_mgr implements GfoInvkAble {
|
||||
public Xog_search_suggest_mgr(Xoa_gui_mgr gui_mgr) {
|
||||
this.app = gui_mgr.App();
|
||||
this.main_win = gui_mgr.Browser_win();
|
||||
cur_cmd = new Xog_search_suggest_cmd(app, this);
|
||||
} private Xoae_app app; private Xog_win_itm main_win; private Js_wtr wtr = new Js_wtr();
|
||||
private int results_max = 10; private boolean log_enabled = false;
|
||||
public boolean Enabled() {return enabled;} private boolean enabled = true;
|
||||
public byte Search_mode() {return search_mode;} public Xog_search_suggest_mgr Search_mode_(byte v) {search_mode = v; return this;} private byte search_mode = Tid_search_mode_all_pages_v2;
|
||||
public int All_pages_extend() {return all_pages_extend;} private int all_pages_extend = 1000; // look ahead by 1000
|
||||
public int All_pages_min() {return all_pages_min;} private int all_pages_min = 10000; // only look at pages > 10 kb
|
||||
public boolean Auto_wildcard() {return auto_wildcard;} private boolean auto_wildcard = false; // automatically add wild-card; EX: Earth -> *Earth*
|
||||
public Gfo_url_arg[] Args_default() {return args_default;} private Gfo_url_arg[] args_default = Gfo_url_arg.Ary_empty;
|
||||
public void Args_default_str_(String v) {
|
||||
this.args_default_str = v;
|
||||
byte[] bry = Bry_.new_u8("http://x.org/a?" + v);
|
||||
Gfo_url tmp_url = new Gfo_url();
|
||||
app.Utl__url_parser().Url_parser().Parse(tmp_url, bry, 0, bry.length);
|
||||
args_default = tmp_url.Args();
|
||||
}
|
||||
private String args_default_str = "";// default args for search
|
||||
public static final int[] Ns_default_main = new int[] {Xow_ns_.Id_main};
|
||||
public void Cancel() {
|
||||
cur_cmd.Cancel();
|
||||
long prv_time = Env_.TickCount();
|
||||
while (cur_cmd.Working()) {
|
||||
if (Env_.TickCount() - prv_time > 4000) {
|
||||
if (log_enabled) app.Usr_dlg().Log_many("", "", "search cancel timeout: word=~{0}", String_.new_u8(search_bry));
|
||||
cur_cmd.Working_(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void Search(Xowe_wiki wiki, byte[] search_bry, byte[] cbk_func) {
|
||||
this.wiki = wiki; this.search_bry = search_bry; this.cbk_func = cbk_func;
|
||||
Thread_adp_.invk_(gplx.xowa.apps.Xoa_thread_.Key_special_suggest, this, Invk_search_async).Start();
|
||||
} private Xowe_wiki wiki; private byte[] search_bry, cbk_func;
|
||||
private Object thread_lock = new Object();
|
||||
private void Search_async() {
|
||||
if (!enabled) return;
|
||||
if (search_bry.length == 0) return;
|
||||
this.Cancel();
|
||||
synchronized (thread_lock) {
|
||||
if (Bry_.Eq(search_bry , last_search_bry)) {
|
||||
if (log_enabled) app.Usr_dlg().Log_many("", "", "search repeated?: word=~{0}", String_.new_u8(search_bry));
|
||||
return;
|
||||
}
|
||||
cur_cmd.Init(wiki, search_bry, results_max, search_mode, all_pages_extend, all_pages_min);
|
||||
this.last_search_bry = search_bry;
|
||||
if (log_enabled) app.Usr_dlg().Log_many("", "", "search bgn: word=~{0}", String_.new_u8(search_bry));
|
||||
cur_cmd.Search();
|
||||
}
|
||||
} private Xog_search_suggest_cmd cur_cmd; byte[] last_search_bry;
|
||||
public void Notify() {// EX: receiveSuggestions('search_word', ['result_1', 'result_2']);
|
||||
// synchronized (thread_lock) NOTE: never use synchronized here; will synchronized search; DATE:2013-09-24
|
||||
byte[] search_bry = cur_cmd.Search_bry();
|
||||
if (!Bry_.Eq(search_bry, last_search_bry)) {
|
||||
if (log_enabled) app.Usr_dlg().Log_many("", "", "search does not match?: expd=~{0} actl=~{1}", String_.new_u8(last_search_bry), String_.new_u8(search_bry));
|
||||
return; // do not notify if search terms do not match
|
||||
}
|
||||
List_adp found = cur_cmd.Results();
|
||||
wtr.Func_init(cbk_func);
|
||||
wtr.Prm_bry(search_bry);
|
||||
wtr.Prm_spr();
|
||||
wtr.Ary_init();
|
||||
int len = found.Count();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Xowd_page_itm p = (Xowd_page_itm)found.Get_at(i);
|
||||
Xow_ns ns = wiki.Ns_mgr().Ids_get_or_null(p.Ns_id());
|
||||
byte[] ttl = Xoa_ttl.Replace_unders(ns.Gen_ttl(p.Ttl_page_db()));
|
||||
wtr.Ary_bry(ttl);
|
||||
}
|
||||
wtr.Ary_term();
|
||||
wtr.Func_term();
|
||||
if (log_enabled) app.Usr_dlg().Log_many("", "", "search end: word=~{0}", String_.new_u8(search_bry));
|
||||
main_win.Active_html_box().Html_js_eval_script(wtr.To_str_and_clear());
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_search_async)) Search_async();
|
||||
else if (ctx.Match(k, Invk_notify)) Notify();
|
||||
else if (ctx.Match(k, Invk_enabled)) return Yn.Xto_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.Xto_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.Xto_str(log_enabled);
|
||||
else if (ctx.Match(k, Invk_log_enabled_)) log_enabled = m.ReadYn("v");
|
||||
else if (ctx.Match(k, Invk_args_default)) return args_default_str;
|
||||
else if (ctx.Match(k, Invk_args_default_)) Args_default_str_(m.ReadStr("v"));
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
return this;
|
||||
}
|
||||
public static final String Invk_search_async = "search_async", Invk_notify = "notify", Invk_enabled = "enabled", Invk_enabled_ = "enabled_", Invk_results_max = "results_max", Invk_results_max_ = "results_max_"
|
||||
, Invk_search_mode = "search_mode", Invk_search_mode_ = "search_mode_", Invk_search_mode_list = "search_mode_list"
|
||||
, Invk_all_pages_extend = "all_pages_extend", Invk_all_pages_extend_ = "all_pages_extend_"
|
||||
, Invk_all_pages_min = "all_pages_min", Invk_all_pages_min_ = "all_pages_min_"
|
||||
, Invk_auto_wildcard = "auto_wildcard", Invk_auto_wildcard_ = "auto_wildcard_"
|
||||
, Invk_log_enabled = "log_enabled", Invk_log_enabled_ = "log_enabled_"
|
||||
, Invk_args_default = "args_default", Invk_args_default_ = "args_default_"
|
||||
;
|
||||
private static final String Str_search_mode_search = "Search", Str_search_mode_all_pages_v1 = "AllPages", Str_search_mode_all_pages_v2 = "AllPages_(v2)";
|
||||
public static final byte Tid_search_mode_all_pages_v1 = 0, Tid_search_mode_search = 1, Tid_search_mode_all_pages_v2 = 2;
|
||||
private static KeyVal[] Options_search_mode_list = KeyVal_.Ary(KeyVal_.new_(Str_search_mode_search), KeyVal_.new_(Str_search_mode_all_pages_v1), KeyVal_.new_(Str_search_mode_all_pages_v2));
|
||||
private static byte Search_mode_parse(String v) {
|
||||
if (String_.Eq(v, Str_search_mode_search)) return Tid_search_mode_search;
|
||||
else if (String_.Eq(v, Str_search_mode_all_pages_v1)) return Tid_search_mode_all_pages_v1;
|
||||
else if (String_.Eq(v, Str_search_mode_all_pages_v2)) return Tid_search_mode_all_pages_v2;
|
||||
else throw Exc_.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 Exc_.new_unhandled(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
219
400_xowa/src/gplx/xowa/specials/search/Xosrh_core_tst.java
Normal file
219
400_xowa/src/gplx/xowa/specials/search/Xosrh_core_tst.java
Normal file
@@ -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.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import org.junit.*; import gplx.xowa.tdbs.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
public class Xosrh_core_tst {
|
||||
// @Before public void Init() {fxt.Clear();} private Xos_search_mgr_fxt fxt = new Xos_search_mgr_fxt();
|
||||
@Test public void Basic() {
|
||||
// fxt.Init_basic();
|
||||
// fxt.Test_search_exact("b2", "B2_22", "B2_12", "B2__2");
|
||||
// fxt.Test_search_exact("a" , "A___0");
|
||||
// fxt.Test_search_exact("b1a"); // missing: mid
|
||||
// fxt.Test_search_exact("d"); // missing: end
|
||||
// fxt.Test_search_exact("$"); // missing: bgn
|
||||
// fxt.Test_search_match_bgn("b*", "B3_23", "B2_22", "B1_21", "B3_13", "B2_12", "B1_11", "B3__3", "B2__2", "B1__1");
|
||||
}
|
||||
// @Test public void Page_size() {
|
||||
// fxt.Init_basic();
|
||||
// fxt.Search_mgr().Page_mgr().Itms_per_page_(1);
|
||||
// fxt.Test_search("b*", 0, "B3_23");
|
||||
// fxt.Test_search("b*", 1, "B2_22");
|
||||
// fxt.Test_search("b*", 2, "B1_21");
|
||||
// fxt.Test_search("b*", 3, "B3_13");
|
||||
// }
|
||||
// @Test public void Url() {
|
||||
// Xoa_url url = Xoa_url_parser.Parse_url(fxt.App(), fxt.Wiki(), "Special:Search/Abc?fulltext=y&xowa_sort=len_desc");
|
||||
// fxt.Search_mgr().Args_mgr().Clear().Parse(url.Args());
|
||||
// Tfds.Eq(Xosrh_rslt_itm_sorter.Tid_len_dsc, fxt.Search_mgr().Args_mgr().Sort_tid());
|
||||
// }
|
||||
// @Test public void Url_arg_title() {// http://en.wikipedia.org/wiki/Special:Search/Earth?fulltext=yes&title=Mars
|
||||
// fxt.Test_url_search_bry("Special:Search?fulltext=y&search=Abc" , "Abc"); // query arg
|
||||
//// fxt.Test_url_search_bry("Special:Search/Abc?fulltext=y" , "Abc"); // leaf
|
||||
// fxt.Test_url_search_bry("Special:Search/Abc?fulltext=y&search=Def" , "Def"); // leaf overrides query arg
|
||||
// }
|
||||
// @Test public void Url_ns() {
|
||||
// fxt.Test_url__ns("Special:Search?search=Abc&ns0=1&ns1=1", "0|1");
|
||||
// fxt.Test_url__ns("Special:Search?search=Abc&ns*=1", "*");
|
||||
// fxt.Test_url__ns("Special:Search?search=Abc", "0");
|
||||
// }
|
||||
// @Test public void Html() {
|
||||
// fxt.Init_basic();
|
||||
// fxt.Test_html_by_url("B1", "", String_.Concat_lines_nl
|
||||
// ( "Result '''1''' of '''3''' for '''B1'''<br/>"
|
||||
// , "{|"
|
||||
// , "|-"
|
||||
// , "| [[Special:Search/B1?fulltext=y&xowa_page_index=0|<]]"
|
||||
// , "| [[Special:Search/B1?fulltext=y&xowa_page_index=1|>]]"
|
||||
// , "|-"
|
||||
// , "| [[Special:Search/B1?fulltext=y&xowa_sort=len_desc|length]]"
|
||||
// , "| [[Special:Search/B1?fulltext=y&xowa_sort=title_asc|title]]"
|
||||
// , "|-"
|
||||
// , "| 42 || [[B1 21]]"
|
||||
// , "|-"
|
||||
// , "| 22 || [[B1 11]]"
|
||||
// , "|-"
|
||||
// , "| 2 || [[B1 1]]"
|
||||
// , "|-"
|
||||
// , "| [[Special:Search/B1?fulltext=y&xowa_page_index=0|<]]"
|
||||
// , "| [[Special:Search/B1?fulltext=y&xowa_page_index=1|>]]"
|
||||
// , "|}"
|
||||
// ));
|
||||
// }
|
||||
//// @Test public void Page_next() {
|
||||
//// fxt.Init_basic();
|
||||
//// fxt.Search_mgr().Page_size_(1);
|
||||
//// fxt.Test_search(Xows_page__search.Match_tid_all, "B1", 0, "B1 1");
|
||||
//// fxt.Test_search(Xows_page__search.Match_tid_all, "B1", 1, "B1 11");
|
||||
//// }
|
||||
//// @Test public void Misc_url() {
|
||||
//// fxt.Init_basic();
|
||||
//// fxt.Search_mgr().Page_size_(1);
|
||||
//// fxt.Expd_address_page_("Special:Search/B1");
|
||||
//// fxt.Test_search(Xows_page__search.Match_tid_all, "B1", 0, "B1 1");
|
||||
//// }
|
||||
// @Test public void Sort_defaults_to_len_desc() {
|
||||
// fxt.Init_basic();
|
||||
// fxt.Search_mgr().Page_mgr().Itms_per_page_(3);
|
||||
// fxt.Test_search2(Xows_page__search.Match_tid_bgn, "b" , 0, Xosrh_rslt_itm_sorter.Tid_ttl_asc , "B1_11", "B1_21", "B1__1"); // sort by name; note that _ sorts after alphabet
|
||||
// fxt.Test_search2(Xows_page__search.Match_tid_bgn, "b" , 1, Xosrh_rslt_itm_sorter.Tid_none , "B2_12", "B2_22", "B2__2"); // sort by name still; next page should not reset
|
||||
// fxt.Test_search2(Xows_page__search.Match_tid_bgn, "b2" , 0, Xosrh_rslt_itm_sorter.Tid_none , "B2_22", "B2_12", "B2__2"); // sort by len desc; new search should reset
|
||||
// }
|
||||
}
|
||||
// class Xos_search_mgr_fxt {
|
||||
// Xoae_app app; Xowe_wiki wiki; Bry_bfr bfr = Bry_bfr.reset_(500); Xows_page__search search_mgr;
|
||||
// public Xoae_app App() {return app;}
|
||||
// public Xowe_wiki Wiki() {return wiki;}
|
||||
// public Xobl_regy_itm regy_itm_(int id, String bgn, String end, int count) {return new Xobl_regy_itm(id, Bry_.new_u8(bgn), Bry_.new_u8(end), count);}
|
||||
// public Xowd_page_itm data_ttl_(int id, String ttl) {return data_ttl_(id, 0, 0, false, 0, ttl);}
|
||||
// public Xowd_page_itm data_ttl_(int id, int fil, int row, boolean redirect, int len, String ttl) {return new Xowd_page_itm().Init(id, Bry_.new_u8(ttl), redirect, len, fil, row);}
|
||||
// public Xowd_page_itm data_id_(int id, String ttl) {return data_id_(id, Xow_ns_.Id_main, ttl);}
|
||||
// public Xowd_page_itm data_id_(int id, int ns, String ttl) {return new Xowd_page_itm().Id_(id).Ns_id_(ns).Ttl_page_db_(Bry_.new_u8(ttl)).Text_db_id_(0).Text_len_(0);}
|
||||
// public Xobl_search_ttl data_sttl_(String word, params int[] ids) {return new Xobl_search_ttl(Bry_.new_u8(word), data_ttl_word_page_ary_(ids));}
|
||||
// public Xobl_search_ttl_page[] data_ttl_word_page_ary_(params int[] ids) {
|
||||
// int ids_len = ids.length;
|
||||
// Xobl_search_ttl_page[] rv = new Xobl_search_ttl_page[ids_len];
|
||||
// for (int i = 0; i < ids_len; i++) {
|
||||
// int id = ids[i];
|
||||
// rv[i] = new Xobl_search_ttl_page(id, id * 2);
|
||||
// }
|
||||
// return rv;
|
||||
// }
|
||||
// public void Init_regy_site(byte dir_info, params Xobl_regy_itm[] ary) {Init_regy(wiki.Tdb_fsys_mgr().Url_site_reg(dir_info), ary);}
|
||||
// public void Init_regy_ns (String ns_num, byte tid, params Xobl_regy_itm[] ary) {Init_regy(wiki.Tdb_fsys_mgr().Url_ns_reg(ns_num, tid), ary);}
|
||||
// public void Init_regy(Io_url url, Xobl_regy_itm[] ary) {
|
||||
// int ary_len = ary.length;
|
||||
// for (int i = 0; i < ary_len; i++) {
|
||||
// Xobl_regy_itm itm = ary[i];
|
||||
// itm.Srl_save(tmp_bfr);
|
||||
// }
|
||||
// Io_mgr.I.SaveFilBfr(url, tmp_bfr);
|
||||
// } private Bry_bfr tmp_bfr = Bry_bfr.reset_(255);
|
||||
// public void Init_data(Io_url fil, params Xobl_data_itm[] ary) {
|
||||
// Xob_xdat_file xdat_file = new Xob_xdat_file();
|
||||
// int ary_len = ary.length;
|
||||
// for (int i = 0; i < ary_len; i++) {
|
||||
// Xobl_data_itm itm = ary[i];
|
||||
// itm.Srl_save(tmp_bfr);
|
||||
// xdat_file.Insert(bfr, tmp_bfr.Xto_bry_and_clear());
|
||||
// }
|
||||
// xdat_file.Save(fil);
|
||||
// }
|
||||
// public void Init_basic() {
|
||||
// this.Init_regy_ns(wiki.Ns_mgr().Ns_main().Num_str(), Xotdb_dir_info_.Tid_search_ttl, this.regy_itm_(0, "A", "C", 5));
|
||||
// this.Init_data(wiki.Tdb_fsys_mgr().Url_ns_fil(Xotdb_dir_info_.Tid_search_ttl, Xow_ns_.Id_main, 0)
|
||||
// , this.data_sttl_("a" , 0)
|
||||
// , this.data_sttl_("b1" , 1, 11, 21)
|
||||
// , this.data_sttl_("b2" , 2, 12, 22)
|
||||
// , this.data_sttl_("b3" , 3, 13, 23)
|
||||
// , this.data_sttl_("c" , 4)
|
||||
// );
|
||||
// this.Init_regy_site(Xotdb_dir_info_.Tid_id, this.regy_itm_(0, "A", "C", 11));
|
||||
// this.Init_data(wiki.Tdb_fsys_mgr().Url_site_fil(Xotdb_dir_info_.Tid_id, 0)
|
||||
// , this.data_id_( 0, "A___0")
|
||||
// , this.data_id_( 1, "B1__1")
|
||||
// , this.data_id_( 2, "B2__2")
|
||||
// , this.data_id_( 3, "B3__3")
|
||||
// , this.data_id_( 4, "C___4")
|
||||
// , this.data_id_(11, "B1_11")
|
||||
// , this.data_id_(12, "B2_12")
|
||||
// , this.data_id_(13, "B3_13")
|
||||
// , this.data_id_(21, "B1_21")
|
||||
// , this.data_id_(22, "B2_22")
|
||||
// , this.data_id_(23, "B3_23")
|
||||
// );
|
||||
// search_mgr.Page_mgr().Ns_mgr().Add_all(); // WORKAROUND: xdat fmt does not store ns with search data; pages will be retrieved with ns_id = null; force ns_all (instead of allowing ns_main default);
|
||||
// }
|
||||
// public void Clear() {
|
||||
// Io_mgr.I.InitEngine_mem();
|
||||
// app = Xoa_app_fxt.app_();
|
||||
// wiki = Xoa_app_fxt.wiki_tst_(app);
|
||||
// search_mgr = wiki.Special_mgr().Page_search();
|
||||
// wiki.Appe().Gui_mgr().Search_suggest_mgr().Args_default_str_("ns*=1"); // WORKAROUND: xdat fmt does not store ns with search data; pages will be retrieved with ns_id = null; force ns_all (instead of allowing ns_main default);
|
||||
// }
|
||||
// public Xows_page__search Search_mgr() {return search_mgr;}
|
||||
// public void Test_url_search_bry(String url_str, String expd) {
|
||||
// Xoa_url url = Xoa_url_parser.Parse_url(app, wiki, url_str);
|
||||
// search_mgr.Args_mgr().Clear().Parse(url.Args());
|
||||
// Tfds.Eq(expd, String_.new_u8(search_mgr.Args_mgr().Search_bry()));
|
||||
// }
|
||||
// public void Test_url__ns(String url_str, String expd) {
|
||||
// Xoa_url url = Xoa_url_parser.Parse_url(app, wiki, url_str);
|
||||
// search_mgr.Args_mgr().Clear().Parse(url.Args());
|
||||
// Tfds.Eq(expd, String_.new_a7(search_mgr.Args_mgr().Ns_mgr().Xto_hash_key()));
|
||||
// }
|
||||
// public void Test_search_exact(String ttl_str, params String[] expd_ary) {Test_search(ttl_str, 0, expd_ary);}
|
||||
// public void Test_search_match_bgn(String ttl_str, params String[] expd_ary) {Test_search(ttl_str, 0, expd_ary);}
|
||||
// public void Test_search(String ttl_str, int page_idx, params String[] expd_ary) {
|
||||
// byte[] ttl_bry = Bry_.new_a7(ttl_str);
|
||||
// Bry_bfr bfr = wiki.Utl__bfr_mkr().Get_b128();
|
||||
// Xosrh_rslt_grp page = search_mgr.Page_mgr().Search(bfr, wiki, ttl_bry, page_idx, search_mgr.Page_mgr());
|
||||
// bfr.Mkr_rls();
|
||||
// Tfds.Eq_ary(expd_ary, Search_itms_to_int_ary(page));
|
||||
// }
|
||||
// public void Test_html_by_url(String ttl_str, String args_str, String expd_html) {
|
||||
// wiki.Init_needed_(false);
|
||||
// byte[] ttl_bry = Bry_.new_a7(ttl_str);
|
||||
// Xoa_ttl ttl = Xoa_ttl.parse_(wiki, ttl_bry);
|
||||
// Xoae_page page = Xoae_page.test_(wiki, ttl);
|
||||
// byte[] url_bry = Bry_.new_u8("http://en.wikipedia.org/wiki/Special:Search/" + ttl_str + args_str);
|
||||
// Xoa_url url = wiki.Appe().Url_parser().Parse(url_bry);
|
||||
// search_mgr.Special_gen(url, page, wiki, ttl);
|
||||
// Tfds.Eq_str_lines(expd_html, String_.new_u8(page.Root().Data_htm()));
|
||||
// }
|
||||
// public void Test_search2(byte match_tid, String ttl_str, int page_idx, byte sort_tid, params String[] expd_ary) {
|
||||
// Bry_bfr bfr = wiki.Utl__bfr_mkr().Get_b128();
|
||||
// Xoa_url_parser url_parser = new Xoa_url_parser();
|
||||
// byte[] url_raw = Bry_.new_a7("Special:Search/" + ttl_str + ((match_tid == Xows_page__search.Match_tid_all) ? "" : "*") + "?fulltext=y" + Xosrh_rslt_itm_sorter.Xto_url_arg(sort_tid) + "&xowa_page_size=1&xowa_page_index=" + page_idx);
|
||||
// Xoa_url url = url_parser.Parse(url_raw);
|
||||
// Xoa_ttl ttl = Xoa_ttl.parse_(wiki, url_raw);
|
||||
// Xoae_page page = wiki.Ctx().Cur_page();
|
||||
// search_mgr.Special_gen(url, page, wiki, ttl);
|
||||
// Xosrh_rslt_grp cur_grp = search_mgr.Cur_grp();
|
||||
// bfr.Mkr_rls();
|
||||
// Tfds.Eq_ary(expd_ary, Search_itms_to_int_ary(cur_grp));
|
||||
// }
|
||||
// String[] Search_itms_to_int_ary(Xosrh_rslt_grp page) {
|
||||
// int itms_len = page.Itms_len();
|
||||
// String[] rv = new String[itms_len];
|
||||
// for (int i = 0; i < itms_len; i++) {
|
||||
// Xowd_page_itm itm = page.Itms_get_at(i);
|
||||
// rv[i] = String_.new_u8(itm.Ttl_page_db());
|
||||
// }
|
||||
// return rv;
|
||||
// }
|
||||
// }
|
||||
98
400_xowa/src/gplx/xowa/specials/search/Xosrh_page_mgr.java
Normal file
98
400_xowa/src/gplx/xowa/specials/search/Xosrh_page_mgr.java
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.xowa.wikis.data.tbls.*;
|
||||
public class Xosrh_page_mgr implements Xosrh_page_mgr_searcher {
|
||||
public int Pages_len() {return pages_ary.length;}
|
||||
public int Itms_bgn() {return itms_bgn;} private int itms_bgn;
|
||||
public int Itms_end() {return itms_end;} private int itms_end;
|
||||
public int Itms_per_page() {return itms_per_page;} public Xosrh_page_mgr Itms_per_page_(int v) {itms_per_page = v; return this;} private int itms_per_page = 100;
|
||||
public byte Sort_tid() {return sort_tid;}
|
||||
public Xosrh_page_mgr Sort_tid_(byte v) {
|
||||
if (sort_tid == v) return this;
|
||||
sort_tid = v;
|
||||
sorter.Tid_(v);
|
||||
prv_search_bry = Bry_.Empty; // reset search
|
||||
return this;
|
||||
} byte sort_tid;
|
||||
private byte[] prv_search_bry = Bry_.Empty, prv_ns_bry = Bry_.Empty;
|
||||
public boolean Prv_search_is_same(byte[] cur_search_bry, byte[] cur_ns_bry) {
|
||||
return Bry_.Eq(cur_ns_bry, prv_ns_bry) && Bry_.Eq(cur_search_bry, prv_search_bry);
|
||||
}
|
||||
private Xosrh_rslt_grp[] pages_ary; List_adp cur_ids = List_adp_.new_();
|
||||
private Xosrh_rslt_itm_sorter sorter = new Xosrh_rslt_itm_sorter();
|
||||
private Xowe_wiki wiki;
|
||||
public Xows_ns_mgr Ns_mgr() {return ns_mgr;} public void Ns_mgr_(Xows_ns_mgr v) {ns_mgr = v;} private Xows_ns_mgr ns_mgr = new Xows_ns_mgr();
|
||||
public Xosrh_rslt_grp Search(Bry_bfr bfr, Xowe_wiki wiki, byte[] search, int page_idx, Xosrh_page_mgr_searcher searcher) {return Search(bfr, wiki, search, page_idx, searcher, Cancelable_.Never);}
|
||||
public Xosrh_rslt_grp Search(Bry_bfr bfr, Xowe_wiki wiki, byte[] search, int page_idx, Xosrh_page_mgr_searcher searcher, Cancelable cancelable) {
|
||||
this.wiki = wiki;
|
||||
Xosrh_rslt_grp rv = null;
|
||||
itms_bgn = page_idx * itms_per_page;
|
||||
itms_end = itms_bgn + itms_per_page;
|
||||
if (Prv_search_is_same(search, ns_mgr.To_hash_key())) { // search is same
|
||||
if (page_idx < pages_ary.length) { // page_idx is in bounds
|
||||
rv = pages_ary[page_idx];
|
||||
if (rv != null) return rv; // page_found; return it;
|
||||
}
|
||||
}
|
||||
else { // search is new; rebuild;
|
||||
List_adp ids = searcher.Parse_search_and_load_ids(cancelable, bfr, ns_mgr, search);
|
||||
Rebuild(cancelable, wiki, ids);
|
||||
prv_search_bry = search;
|
||||
prv_ns_bry = ns_mgr.To_hash_key();
|
||||
}
|
||||
int ids_len = cur_ids.Count();
|
||||
if (itms_end > ids_len) itms_end = ids_len;
|
||||
if (page_idx < 0 || page_idx >= pages_ary.length) return Grp_empty;
|
||||
if ( sort_tid != Xosrh_rslt_itm_sorter.Tid_ttl_asc
|
||||
&& cancelable == Cancelable_.Never // cancelable != Cancelable_.Never for search_suggest
|
||||
&& wiki.Db_mgr().Tid() == gplx.xowa.dbs.Xodb_mgr_txt.Tid_txt // txt only has search_title fields (page_id, word_id), so it needs to do another load to get page fields; note that sql has page fields already
|
||||
) {
|
||||
wiki.Db_mgr().Load_mgr().Load_by_ids(cancelable, cur_ids, itms_bgn, itms_end);
|
||||
}
|
||||
rv = new Xosrh_rslt_grp(page_idx);
|
||||
for (int i = itms_bgn; i < itms_end; i++)
|
||||
rv.Itms_add((Xowd_page_itm)cur_ids.Get_at(i));
|
||||
pages_ary[page_idx] = rv;
|
||||
rv.Itms_total_(cur_ids.Count());
|
||||
return rv;
|
||||
}
|
||||
public List_adp Parse_search_and_load_ids(Cancelable cancelable, Bry_bfr bfr, Xows_ns_mgr ns_mgr, byte[] search) {
|
||||
search = wiki.Lang().Case_mgr().Case_build_lower(search, 0, search.length);
|
||||
Xosrh_qry_itm cur_root = Xosrh_parser._.Parse(search);
|
||||
cur_root.Search(cancelable, bfr, search, wiki, itms_per_page, ns_mgr);
|
||||
return cur_root.Matches(search).Ids();
|
||||
}
|
||||
private void Rebuild(Cancelable cancelable, Xowe_wiki wiki, List_adp ids) {
|
||||
int ids_len = ids.Count();
|
||||
int pages_len = ((ids_len - 1) / itms_per_page) + 1; if (pages_len == 0) pages_len = 1;
|
||||
pages_ary = new Xosrh_rslt_grp[pages_len];
|
||||
cur_ids.Clear();
|
||||
for (int i = 0; i < ids_len; i++)
|
||||
cur_ids.Add(ids.Get_at(i));
|
||||
if (sort_tid == Xosrh_rslt_itm_sorter.Tid_ttl_asc) {
|
||||
cur_ids.Sort_by(sorter.Tid_(Xosrh_rslt_itm_sorter.Tid_id));
|
||||
wiki.Db_mgr().Load_mgr().Load_by_ids(cancelable, cur_ids, 0, ids_len);
|
||||
cur_ids.Sort_by(sorter.Tid_(Xosrh_rslt_itm_sorter.Tid_ttl_asc));
|
||||
}
|
||||
else {
|
||||
cur_ids.Sort_by(sorter.Tid_(Xosrh_rslt_itm_sorter.Tid_len_dsc));
|
||||
}
|
||||
}
|
||||
private static final Xosrh_rslt_grp Grp_empty = new Xosrh_rslt_grp(-1);
|
||||
}
|
||||
@@ -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.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
public interface Xosrh_page_mgr_searcher {
|
||||
List_adp Parse_search_and_load_ids(Cancelable cancelable, Bry_bfr bfr, Xows_ns_mgr ns_Mgr, byte[] search);
|
||||
}
|
||||
@@ -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.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import org.junit.*; import gplx.xowa.tdbs.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
public class Xosrh_page_mgr_tst {
|
||||
@Before public void init() {fxt.Clear();} private Xosrh_page_mgr_fxt fxt = new Xosrh_page_mgr_fxt();
|
||||
@Test public void Basic() {
|
||||
fxt.Init_itms_per_page_(3).Init_site_ids(10, 20);
|
||||
Xosrh_page_mgr_searcher ids_a = fxt.ids_(10, 17);
|
||||
fxt.Test_search("A", ids_a, 0, Int_.Ary(16, 15, 14));
|
||||
fxt.Test_search("A", ids_a, 1, Int_.Ary(13, 12, 11));
|
||||
fxt.Test_search("A", ids_a, 2, Int_.Ary(10));
|
||||
fxt.Test_search("A", ids_a, 0, Int_.Ary(16, 15, 14));
|
||||
Xosrh_page_mgr_searcher ids_b = fxt.ids_(17, 20);
|
||||
fxt.Init_sort_by_name_(true).Test_search("B", ids_b, 0, Int_.Ary(17, 18, 19));
|
||||
}
|
||||
}
|
||||
class Xosrh_page_mgr_fxt {
|
||||
public Xosrh_page_mgr_fxt Clear() {
|
||||
if (app == null) {
|
||||
app = Xoa_app_fxt.app_();
|
||||
wiki = Xoa_app_fxt.wiki_tst_(app);
|
||||
tmp_bfr = Bry_bfr.reset_(255);
|
||||
page_mgr = new Xosrh_page_mgr();
|
||||
hive_mgr = new Xowd_hive_mgr(wiki, Xotdb_dir_info_.Tid_id);
|
||||
}
|
||||
return this;
|
||||
} private Xoae_app app; Xowe_wiki wiki; Bry_bfr tmp_bfr; Xosrh_page_mgr page_mgr; Xowd_hive_mgr hive_mgr;
|
||||
public Xosrh_page_mgr_fxt Init_site_ids(int bgn, int end) {
|
||||
Xowd_page_itm tmp_itm = new Xowd_page_itm();
|
||||
for (int i = bgn; i < end; i++) {
|
||||
byte[] id_bry = new byte[5]; // NOTE: do not reuse; will break hive_mgr
|
||||
Base85_utl.XtoStrByAry(i, id_bry, 0, 5);
|
||||
tmp_itm.Ns_id_(Xow_ns_.Id_main).Init(i, Bry_.XtoStrBytesByInt(i, 0), false, 10, 0, i - bgn);
|
||||
Xotdb_page_itm_.Txt_id_save(tmp_bfr, tmp_itm);
|
||||
hive_mgr.Create(id_bry, tmp_bfr.Xto_bry_and_clear(), null);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
// public Xowd_page_itm Set_all(int id, int fil_idx, int row_idx, boolean type_redirect, int itm_len, int ns_id, byte[] ttl) {
|
||||
public Xosrh_page_mgr_fxt Init_sort_by_name_(boolean v) {page_mgr.Sort_tid_(v ? Xosrh_rslt_itm_sorter.Tid_ttl_asc : Xosrh_rslt_itm_sorter.Tid_len_dsc); return this;}
|
||||
public Xosrh_page_mgr_fxt Init_itms_per_page_(int v) {page_mgr.Itms_per_page_(v); return this;}
|
||||
public Xosrh_page_mgr_searcher_mok ids_(int bgn, int end) {
|
||||
List_adp rv = List_adp_.new_();
|
||||
int len = end - bgn;
|
||||
for (int i = 0; i < len; i++) {
|
||||
int itm_id = i + bgn;
|
||||
int itm_len = itm_id;
|
||||
Xowd_page_itm itm = Xowd_page_itm.new_srch(itm_id, itm_len);
|
||||
rv.Add(itm);
|
||||
}
|
||||
return new Xosrh_page_mgr_searcher_mok(rv);
|
||||
}
|
||||
public void Test_search(String search_str, Xosrh_page_mgr_searcher searcher, int page_idx, int[] expd) {
|
||||
byte[] search_bry = Bry_.new_a7(search_str);
|
||||
Xosrh_rslt_grp page = page_mgr.Search(tmp_bfr, wiki, search_bry, page_idx, searcher);
|
||||
Tfds.Eq_ary(expd, Xto_int_ary(page));
|
||||
}
|
||||
int[] Xto_int_ary(Xosrh_rslt_grp page) {
|
||||
int len = page.Itms_len();
|
||||
int[] rv = new int[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
rv[i] = ((Xowd_page_itm)page.Itms_get_at(i)).Id();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
class Xosrh_page_mgr_searcher_mok implements Xosrh_page_mgr_searcher {
|
||||
public Xosrh_page_mgr_searcher_mok(List_adp list) {this.list = list;} List_adp list;
|
||||
public List_adp Parse_search_and_load_ids(Cancelable cancelable, Bry_bfr bfr, Xows_ns_mgr ns_mgr, byte[] search) {return list;}
|
||||
}
|
||||
88
400_xowa/src/gplx/xowa/specials/search/Xosrh_parser.java
Normal file
88
400_xowa/src/gplx/xowa/specials/search/Xosrh_parser.java
Normal file
@@ -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.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
class Xosrh_parser {
|
||||
public Xosrh_qry_itm Parse(byte[] src) {
|
||||
this.src = src;
|
||||
Xosrh_qry_tkn[] tkns = Xosrh_scanner._.Scan(src);
|
||||
return Parse_itm_or(make_ctx.Init(tkns));
|
||||
} private Xosrh_parser_ctx make_ctx = new Xosrh_parser_ctx(); byte[] src;
|
||||
Xosrh_qry_itm Parse_itm_or(Xosrh_parser_ctx make_ctx) {
|
||||
Xosrh_qry_itm lhs = Parse_itm_and(make_ctx);
|
||||
while (make_ctx.Cur_tid(Xosrh_qry_tkn.Tid_or)) {
|
||||
make_ctx.Move_next();
|
||||
Xosrh_qry_itm rhs = Parse_itm_and(make_ctx);
|
||||
lhs = Xosrh_qry_itm.nde_(Xosrh_qry_itm.Tid_or, lhs, rhs);
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
Xosrh_qry_itm Parse_itm_and(Xosrh_parser_ctx make_ctx) {
|
||||
Xosrh_qry_itm lhs = Parse_itm_not(make_ctx);
|
||||
while (make_ctx.Cur_tid(Xosrh_qry_tkn.Tid_and)) {
|
||||
make_ctx.Move_next();
|
||||
Xosrh_qry_itm rhs = Parse_itm_not(make_ctx);
|
||||
lhs = Xosrh_qry_itm.nde_(Xosrh_qry_itm.Tid_and, lhs, rhs);
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
Xosrh_qry_itm Parse_itm_not(Xosrh_parser_ctx make_ctx) {
|
||||
Xosrh_qry_itm lhs = Parse_itm_leaf(make_ctx);
|
||||
while (make_ctx.Cur_tid(Xosrh_qry_tkn.Tid_not)) {
|
||||
make_ctx.Move_next();
|
||||
Xosrh_qry_itm rhs = Parse_itm_leaf(make_ctx);
|
||||
lhs = Xosrh_qry_itm.nde_(Xosrh_qry_itm.Tid_not, null, rhs);
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
Xosrh_qry_itm Parse_itm_leaf(Xosrh_parser_ctx make_ctx) {
|
||||
if (make_ctx.Cur_tid(Xosrh_qry_tkn.Tid_paren_bgn)) {
|
||||
make_ctx.Move_next();
|
||||
Xosrh_qry_itm lhs = Parse_itm_or(make_ctx);
|
||||
if (make_ctx.Cur_tid(Xosrh_qry_tkn.Tid_paren_end)) make_ctx.Move_next(); // skip token
|
||||
return lhs;
|
||||
}
|
||||
else if (make_ctx.Cur_tid(Xosrh_qry_tkn.Tid_eos))
|
||||
return Xosrh_qry_itm.Null;
|
||||
else {
|
||||
Xosrh_qry_tkn word_tkn = make_ctx.Move_next();
|
||||
if (word_tkn.Tid() == Xosrh_qry_tkn.Tid_not) {
|
||||
word_tkn = make_ctx.Move_next();
|
||||
if (word_tkn == null) return Xosrh_qry_itm.Null; // occurs in "a -"
|
||||
Xosrh_qry_itm word_itm = Xosrh_qry_itm.word_(src, word_tkn);
|
||||
return Xosrh_qry_itm.nde_(Xosrh_qry_itm.Tid_not, null, word_itm);
|
||||
}
|
||||
else
|
||||
return Xosrh_qry_itm.word_(src, word_tkn);
|
||||
}
|
||||
}
|
||||
public static final Xosrh_parser _ = new Xosrh_parser(); Xosrh_parser() {}
|
||||
}
|
||||
class Xosrh_parser_ctx {
|
||||
public Xosrh_parser_ctx Init(Xosrh_qry_tkn[] ary) {
|
||||
this.ary = ary;
|
||||
ary_len = ary.length;
|
||||
this.pos = 0;
|
||||
return this;
|
||||
} private Xosrh_qry_tkn[] ary; int pos = 0; int ary_len;
|
||||
public boolean Cur_tid(byte tid) {return pos < ary_len ? tid == ary[pos].Tid(): tid == Xosrh_qry_tkn.Tid_eos;}
|
||||
public Xosrh_qry_tkn Move_next() {
|
||||
Xosrh_qry_tkn rv = null;
|
||||
if (pos < ary_len) rv = ary[pos++];
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
168
400_xowa/src/gplx/xowa/specials/search/Xosrh_parser_tst.java
Normal file
168
400_xowa/src/gplx/xowa/specials/search/Xosrh_parser_tst.java
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import org.junit.*; import gplx.xowa.tdbs.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
public class Xosrh_parser_tst {
|
||||
@Before public void init() {fxt.Clear();} private Xosearch_parser_fxt fxt = new Xosearch_parser_fxt();
|
||||
@Test public void Scan_word() {fxt.Test_scan("abc", "abc");}
|
||||
@Test public void Scan_word_many() {fxt.Test_scan("abc d ef", "abc", "AND", "d", "AND", "ef");}
|
||||
@Test public void Scan_word_symbol() {fxt.Test_scan("a, b", "a", "AND", "b");}
|
||||
@Test public void Scan_and_embedded() {fxt.Test_scan("candy", "candy");} // check that andy does not become "AND" + y
|
||||
@Test public void Scan_and_and() {fxt.Test_scan("a andand", "a", "AND", "andand");} // check that andand is word; note that AND is automatically inserted between consecutive words
|
||||
@Test public void Scan_and_parentheses() {fxt.Test_scan("a and(b)", "a", "and", "(", "b", ")");} // check that ( causes and to be treated as separate word
|
||||
@Test public void Scan_not() {fxt.Test_scan("-abc", "-", "abc");}
|
||||
@Test public void Scan_not_and() {fxt.Test_scan("a -bc", "a", "AND", "-", "bc");} // auto-add AND for -
|
||||
@Test public void Scan_space() {fxt.Test_scan(" a b ", "a", "AND", "b");} // spaces should not generate tkns
|
||||
@Test public void Scan_quote() {fxt.Test_scan("\"abc\"", "abc");}
|
||||
@Test public void Scan_complicated() {fxt.Test_scan("(a AND \"b\") OR -c", "(", "a","AND", "b", ")", "OR", "-", "c");}
|
||||
@Test public void Scan_not_embedded() {
|
||||
fxt.Test_scan ("a-b", "a-b"); // fail if "a", "NOT", "b"
|
||||
fxt.Test_scan_tids ("a-b", Xosrh_qry_tkn.Tid_word_quoted); // symbols in unquoted word should convert word to quotes; EX: a-b -> "a-b"
|
||||
}
|
||||
@Test public void Parse_basic() {fxt.Test_parse("abc", "abc");}
|
||||
@Test public void Parse_and() {fxt.Test_parse("abc AND def", "(abc AND def)");}
|
||||
@Test public void Parse_not() {fxt.Test_parse("-abc", "NOT abc");}
|
||||
@Test public void Parse_many() {fxt.Test_parse("A AND B OR C AND D", "((A AND B) OR (C AND D))");}
|
||||
@Test public void Match() {
|
||||
fxt.Init_match("A", 11, 12, 22);
|
||||
fxt.Init_match("B", 21, 22, 12);
|
||||
fxt.Test_match("A OR B" , 11, 12, 22, 21);
|
||||
fxt.Test_match("A AND B" , 22, 12);
|
||||
fxt.Test_match("A AND -B" , 11);
|
||||
}
|
||||
@Test public void Search() {
|
||||
Xosearch_searcher_fxt fxt = new Xosearch_searcher_fxt().Clear();
|
||||
fxt.Init_search("a1", 11, 12);
|
||||
fxt.Init_search("b1", 21, 22);
|
||||
fxt.Init_search("b2", 26, 27);
|
||||
fxt.Init_search("c1", 31, 12);
|
||||
fxt.Test_search("b1", 21, 22);
|
||||
fxt.Test_search("b*", 21, 22, 26, 27);
|
||||
}
|
||||
}
|
||||
class Xosearch_searcher_fxt {
|
||||
public Xosearch_searcher_fxt Clear() {
|
||||
if (app == null) {
|
||||
app = Xoa_app_fxt.app_();
|
||||
wiki = Xoa_app_fxt.wiki_tst_(app);
|
||||
mgr = new Xowd_hive_mgr(wiki, Xotdb_dir_info_.Tid_search_ttl);
|
||||
tmp_bfr = Bry_bfr.reset_(255);
|
||||
parser = Xosrh_parser._;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
Xoae_app app; Xowe_wiki wiki; Xowd_hive_mgr mgr; Bry_bfr tmp_bfr;
|
||||
Xosrh_parser parser;
|
||||
public void Init_search(String ttl_str, int... ids) {
|
||||
byte[] ttl_bry = Bry_.new_a7(ttl_str);
|
||||
tmp_bfr.Add(ttl_bry);
|
||||
int len = ids.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
int id = ids[i];
|
||||
tmp_bfr.Add_byte_pipe();
|
||||
tmp_bfr.Add_base85_len_5(id);
|
||||
tmp_bfr.Add_byte(Byte_ascii.Semic);
|
||||
tmp_bfr.Add_base85_len_5(0);
|
||||
}
|
||||
mgr.Create(wiki.Ns_mgr().Ns_main(), ttl_bry, tmp_bfr.Xto_bry_and_clear(), null);
|
||||
}
|
||||
public void Test_search(String ttl_str, int... expd) {
|
||||
byte[] ttl_bry = Bry_.new_a7(ttl_str);
|
||||
Xosrh_qry_itm qry_root = parser.Parse(ttl_bry);
|
||||
Xows_ns_mgr ns_mgr = new Xows_ns_mgr(); ns_mgr.Add_all(); // WORKAROUND: xdat fmt does not store ns with search data; pages will be retrieved with ns_id = null; force ns_all (instead of allowing ns_main default);
|
||||
qry_root.Search(Cancelable_.Never, tmp_bfr, ttl_bry, wiki, 100, ns_mgr);
|
||||
int[] actl = Xosearch_parser_fxt.Xto_ints(qry_root.Ids());
|
||||
Tfds.Eq_ary(expd, actl);
|
||||
}
|
||||
}
|
||||
class Xosearch_parser_fxt {
|
||||
public Xosearch_parser_fxt Clear() {
|
||||
if (parser == null) {
|
||||
parser = Xosrh_parser._;
|
||||
matches = Ordered_hash_.new_bry_();
|
||||
}
|
||||
matches.Clear();
|
||||
return this;
|
||||
} private Xosrh_parser parser; Ordered_hash matches;
|
||||
public void Init_match(String name, int... ids) {
|
||||
int len = ids.length;
|
||||
List_adp id_vals = List_adp_.new_();
|
||||
for (int i = 0; i < len; i++)
|
||||
id_vals.Add(Xowd_page_itm.new_srch(ids[i], 0));
|
||||
matches.Add(Bry_.new_a7(name), id_vals);
|
||||
}
|
||||
public void Test_match(String raw, int... expd) {
|
||||
byte[] src = Bry_.new_a7(raw);
|
||||
Xosrh_qry_itm qry_root = parser.Parse(src);
|
||||
Test_match_assign_ids(src, qry_root);
|
||||
Xosrh_qry_ids matches = qry_root.Matches(src);
|
||||
Tfds.Eq_ary(expd, Xto_ints(matches.Ids()));
|
||||
}
|
||||
public static int[] Xto_ints(List_adp list) {
|
||||
if (list == null) return Int_.Ary_empty;
|
||||
int len = list.Count();
|
||||
int[] rv = new int[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
rv[i] = ((Xowd_page_itm)list.Get_at(i)).Id();
|
||||
return rv;
|
||||
}
|
||||
private void Test_match_assign_ids(byte[] src, Xosrh_qry_itm itm) {
|
||||
if (itm.Tid() == Xosrh_qry_itm.Tid_word) {
|
||||
byte[] word = itm.Word();
|
||||
List_adp ids = (List_adp)matches.Get_by(word);
|
||||
itm.Ids_(ids);
|
||||
}
|
||||
else {
|
||||
if (itm.Lhs() != null) Test_match_assign_ids(src, itm.Lhs());
|
||||
if (itm.Rhs() != null) Test_match_assign_ids(src, itm.Rhs());
|
||||
}
|
||||
}
|
||||
public void Test_scan(String raw, String... expd) {
|
||||
byte[] src = Bry_.new_a7(raw);
|
||||
Xosrh_qry_tkn[] actl_itms = Xosrh_scanner._.Scan(src);
|
||||
Tfds.Eq_ary(expd, To_strings(src, actl_itms));
|
||||
}
|
||||
public void Test_scan_tids(String raw, byte... expd) {
|
||||
byte[] src = Bry_.new_a7(raw);
|
||||
Xosrh_qry_tkn[] actl_itms = Xosrh_scanner._.Scan(src);
|
||||
Tfds.Eq_ary(expd, To_tids(actl_itms));
|
||||
}
|
||||
String[] To_strings(byte[] src, Xosrh_qry_tkn[] ary) {
|
||||
int len = ary.length;
|
||||
String[] rv = new String[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
Xosrh_qry_tkn tkn = ary[i];
|
||||
rv[i] = String_.new_a7(tkn.Val(src));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
byte[] To_tids(Xosrh_qry_tkn[] ary) {
|
||||
int len = ary.length;
|
||||
byte[] rv = new byte[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
Xosrh_qry_tkn tkn = ary[i];
|
||||
rv[i] = tkn.Tid();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public void Test_parse(String raw, String expd) {
|
||||
byte[] src = Bry_.new_a7(raw);
|
||||
Xosrh_qry_itm qry_root = parser.Parse(src);
|
||||
Tfds.Eq(expd, qry_root.Xto_str(src));
|
||||
}
|
||||
}
|
||||
219
400_xowa/src/gplx/xowa/specials/search/Xosrh_qry_itm.java
Normal file
219
400_xowa/src/gplx/xowa/specials/search/Xosrh_qry_itm.java
Normal file
@@ -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.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.xowa.dbs.*; import gplx.xowa.wikis.data.tbls.*; import gplx.xowa.bldrs.cmds.texts.*;
|
||||
class Xosrh_qry_itm {
|
||||
public Xosrh_qry_itm(byte tid, byte[] word, Xosrh_qry_itm lhs, Xosrh_qry_itm rhs) {
|
||||
this.tid = tid; this.word = word; this.lhs = lhs; this.rhs = rhs;
|
||||
}
|
||||
public byte Tid() {return tid;} private byte tid;
|
||||
public Xosrh_qry_itm Lhs() {return lhs;} private Xosrh_qry_itm lhs;
|
||||
public Xosrh_qry_itm Rhs() {return rhs;} private Xosrh_qry_itm rhs;
|
||||
public List_adp Ids() {return ids;} public void Ids_(List_adp v) {this.ids = v;} List_adp ids = List_adp_.Noop;
|
||||
public byte[] Word() {return word;} private byte[] word;
|
||||
public String Xto_str(byte[] src) {
|
||||
Bry_bfr bfr = Bry_bfr.new_();
|
||||
Xto_str_bld(src, bfr);
|
||||
return bfr.Xto_str_and_clear();
|
||||
}
|
||||
public Xosrh_qry_ids Matches(byte[] src) {
|
||||
switch (tid) {
|
||||
case Xosrh_qry_itm.Tid_word:
|
||||
case Xosrh_qry_itm.Tid_word_quote:
|
||||
return new Xosrh_qry_ids(false, ids);
|
||||
case Xosrh_qry_itm.Tid_not: Xosrh_qry_ids rv = rhs.Matches(src); return rv.Not_(!rv.Not());
|
||||
case Xosrh_qry_itm.Tid_or:
|
||||
case Xosrh_qry_itm.Tid_and:
|
||||
List_adp merged = Evaluate(src, tid == Xosrh_qry_itm.Tid_and, lhs, rhs);
|
||||
return new Xosrh_qry_ids(false, merged);
|
||||
case Xosrh_qry_itm.Tid_null: return Xosrh_qry_ids.Null;
|
||||
default: throw Exc_.new_unhandled(tid);
|
||||
}
|
||||
}
|
||||
private static List_adp Search_word(Xowe_wiki wiki, Cancelable cancelable, Bry_bfr tmp_bfr, Xows_ns_mgr ns_mgr, byte[] search_word, int results_max) {
|
||||
List_adp found = List_adp_.new_();
|
||||
byte wiki_db_tid = wiki.Db_mgr().Tid();
|
||||
if (wiki_db_tid == Xodb_mgr_sql.Tid_sql
|
||||
&& wiki.Appe().Gui_mgr().Search_suggest_mgr().Auto_wildcard()) { // HACK: auto-asterisk words for sqlite; DATE:2013-09-05
|
||||
if (!Bry_.Has_at_end(search_word, new byte[] {Byte_ascii.Star}))
|
||||
search_word = Bry_.Add(search_word, Byte_ascii.Star);
|
||||
if (!Bry_.Has_at_bgn(search_word, new byte[] {Byte_ascii.Star}))
|
||||
search_word = Bry_.Add(Byte_ascii.Star, search_word);
|
||||
}
|
||||
wiki.Db_mgr().Load_mgr().Load_search(cancelable, found, search_word, results_max);
|
||||
List_adp rv = List_adp_.new_();
|
||||
int found_len = found.Count();
|
||||
for (int i = 0; i < found_len; i++) {
|
||||
Xowd_page_itm page = (Xowd_page_itm)found.Get_at(i);
|
||||
if ( ns_mgr.Has(page.Ns_id())
|
||||
|| wiki_db_tid == Xodb_mgr_txt.Tid_txt) // xdat does not store ns, so ns will always be null; no choice but to bring back all results; DATE:2013-11-14
|
||||
rv.Add(page);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public void Search(Cancelable cancelable, Bry_bfr tmp_bfr, byte[] src, Xowe_wiki wiki, int results_max, Xows_ns_mgr ns_mgr) {
|
||||
if (cancelable.Canceled()) return;
|
||||
switch (tid) {
|
||||
case Xosrh_qry_itm.Tid_null: return;
|
||||
case Xosrh_qry_itm.Tid_word:
|
||||
ids = Search_word(wiki, cancelable, tmp_bfr, ns_mgr, word, results_max);
|
||||
break;
|
||||
case Xosrh_qry_itm.Tid_word_quote:
|
||||
Ordered_hash tmp_search_list = Ordered_hash_.new_();
|
||||
byte[][] words = gplx.xowa.bldrs.cmds.texts.Xob_search_base.Split_ttl_into_words(wiki.Lang(), tmp_search_list, tmp_bfr, word);
|
||||
int words_len = words.length;
|
||||
List_adp prv_list = null;
|
||||
for (int i = 0; i < words_len; i++) {
|
||||
if (cancelable.Canceled()) return;
|
||||
List_adp cur_list = Search_word(wiki, cancelable, tmp_bfr, ns_mgr, words[i], results_max);
|
||||
if (prv_list == null) // 1st list; just set to cur_list
|
||||
prv_list = cur_list;
|
||||
else { // nth list; AND to prv_list; "A B" should find all titles with "A AND B"
|
||||
prv_list = Evaluate(word, true, prv_list, false, cur_list, false);
|
||||
}
|
||||
}
|
||||
List_adp tmp_ids = prv_list;
|
||||
int ids_len = tmp_ids.Count();
|
||||
if (ids_len == 0) return;
|
||||
if (cancelable.Canceled()) return;
|
||||
wiki.Db_mgr().Load_mgr().Load_by_ids(cancelable, tmp_ids, 0, ids_len);
|
||||
if (cancelable.Canceled()) return;
|
||||
ids = List_adp_.new_();
|
||||
for (int i = 0; i < ids_len; i++) {
|
||||
Xowd_page_itm itm = (Xowd_page_itm)tmp_ids.Get_at(i);
|
||||
byte[] itm_ttl = itm.Ttl_page_db();
|
||||
itm_ttl = wiki.Lang().Case_mgr().Case_build_lower(itm_ttl, 0, itm_ttl.length); // lowercase ttl (since all search words are lower-cased)
|
||||
itm_ttl = Bry_.Replace(itm_ttl, Byte_ascii.Underline, Byte_ascii.Space); // replace _ with " " (assume user will use spaces in search term)
|
||||
if (Bry_finder.Find_fwd(itm_ttl, word) != Bry_.NotFound)
|
||||
ids.Add(itm);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (lhs != null) lhs.Search(cancelable, tmp_bfr, src, wiki, results_max, ns_mgr);
|
||||
if (rhs != null) rhs.Search(cancelable, tmp_bfr, src, wiki, results_max, ns_mgr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
static final byte Evaluate_tid_null = 0, Evaluate_tid_and = 1, Evaluate_tid_or = 2, Evaluate_tid_not_and = 3;
|
||||
List_adp Evaluate(byte[] src, boolean join_tid_is_and, Xosrh_qry_itm lhs, Xosrh_qry_itm rhs) {
|
||||
Xosrh_qry_ids lhs_grp = lhs.Matches(src), rhs_grp = rhs.Matches(src);
|
||||
boolean lhs_not = lhs_grp.Not(), rhs_not = rhs_grp.Not();
|
||||
List_adp lhs_list = lhs_grp.Ids(), rhs_list = rhs_grp.Ids();
|
||||
if (lhs_not && rhs_not) return Evaluate_not_found("NOT cannot be applied to both lists: lhs:~{0} rhs:~{1}", lhs.Xto_str(src), rhs.Xto_str(src));
|
||||
return Evaluate(src, join_tid_is_and, lhs_list, lhs_not, rhs_list, rhs_not);
|
||||
}
|
||||
/*
|
||||
AND,0 nots: hash a; iterate cur_b and add if in a
|
||||
OR ,0 nots; hash a; add a; iterate cur_b and add if not in a
|
||||
AND,1 nots; hash notted; iterate comp and add only if not in notted; (a,cur_b,c) AND NOT (cur_b)
|
||||
AND,2 nots; fail; NOT xq AND NOT qx will yield all titles
|
||||
OR ,2 nots; fail; NOT xq OR NOT qx will yield all titles
|
||||
OR ,1 nots; fail; (a, cur_b, c, d) OR NOT (xq) will yield all titles
|
||||
*/
|
||||
List_adp Evaluate(byte[] src, boolean join_tid_is_and, List_adp lhs_list, boolean lhs_not, List_adp rhs_list, boolean rhs_not) {
|
||||
List_adp list_to_hash = null, list_to_comp = null; int len = 0;
|
||||
byte tid = Evaluate_tid_null;
|
||||
List_adp rv = List_adp_.new_();
|
||||
if (lhs_not || rhs_not) {
|
||||
if (!join_tid_is_and)
|
||||
return Evaluate_not_found("NOT cannot be applied with OR: lhs:~{0} rhs:~{1}", lhs.Xto_str(src), rhs.Xto_str(src));
|
||||
if (lhs_not) {
|
||||
list_to_hash = lhs_list;
|
||||
list_to_comp = rhs_list;
|
||||
}
|
||||
else {
|
||||
list_to_hash = rhs_list;
|
||||
list_to_comp = lhs_list;
|
||||
}
|
||||
tid = Evaluate_tid_not_and;
|
||||
}
|
||||
else {
|
||||
tid = join_tid_is_and ? Evaluate_tid_and : Evaluate_tid_or;
|
||||
boolean rhs_is_smaller = rhs_list.Count() < lhs_list.Count();
|
||||
if (rhs_is_smaller) {
|
||||
list_to_hash = rhs_list;
|
||||
list_to_comp = lhs_list;
|
||||
}
|
||||
else {
|
||||
list_to_hash = lhs_list;
|
||||
list_to_comp = rhs_list;
|
||||
}
|
||||
}
|
||||
len = list_to_hash.Count();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Xowd_page_itm id = (Xowd_page_itm)list_to_hash.Get_at(i);
|
||||
try {
|
||||
if (!tmp_hash.Has(id.Id_val())) tmp_hash.Add(id.Id_val(), id);
|
||||
} catch (Exception e) {Exc_.Noop(e); tmp_hash.Clear(); return List_adp_.Noop;} // handle error in case of threading issues; must clear tmp_hash else will accumulate;
|
||||
if (tid == Evaluate_tid_or)
|
||||
rv.Add(id);
|
||||
}
|
||||
len = list_to_comp.Count();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Xowd_page_itm id = (Xowd_page_itm)list_to_comp.Get_at(i);
|
||||
boolean exists = tmp_hash.Has(id.Id_val());
|
||||
switch (tid) {
|
||||
case Evaluate_tid_and: // iterate comp and add if in a; EX: (a,cur_b,c) AND (a,d); add a
|
||||
if (exists) rv.Add(id);
|
||||
break;
|
||||
case Evaluate_tid_or: // iterate comp and add if not in a; EX: (a,cur_b,c) OR (a,d); add d
|
||||
case Evaluate_tid_not_and: // iterate comp and add only if not in notted; (a,cur_b,c) AND NOT (cur_b); add a, c
|
||||
if (!exists)
|
||||
rv.Add(id);
|
||||
break;
|
||||
case Evaluate_tid_null: default:
|
||||
throw Exc_.new_unhandled(tid);
|
||||
}
|
||||
}
|
||||
tmp_hash.Clear();
|
||||
return rv;
|
||||
} static Ordered_hash tmp_hash = Ordered_hash_.new_();
|
||||
List_adp Evaluate_not_found(String msg, Object... args) {
|
||||
return null;
|
||||
}
|
||||
public void Xto_str_bld(byte[] src, Bry_bfr bfr) {
|
||||
switch (tid) {
|
||||
case Xosrh_qry_itm.Tid_word: bfr.Add(word); break;
|
||||
case Xosrh_qry_itm.Tid_not: bfr.Add(Bry_not); rhs.Xto_str_bld(src, bfr); break;
|
||||
case Xosrh_qry_itm.Tid_or:
|
||||
case Xosrh_qry_itm.Tid_and:
|
||||
bfr.Add_byte(Byte_ascii.Paren_bgn);
|
||||
lhs.Xto_str_bld(src, bfr);
|
||||
bfr.Add(tid == Xosrh_qry_itm.Tid_or ? Bry_or : Bry_and);
|
||||
rhs.Xto_str_bld(src, bfr);
|
||||
bfr.Add_byte(Byte_ascii.Paren_end);
|
||||
break;
|
||||
case Xosrh_qry_itm.Tid_null: break;
|
||||
default: throw Exc_.new_unhandled(tid);
|
||||
}
|
||||
}
|
||||
public static final byte Tid_null = 0, Tid_root = 1, Tid_word = 2, Tid_word_quote = 3, Tid_not = 4, Tid_or = 5, Tid_and = 6;
|
||||
public static byte[] Bry_not = Bry_.new_a7("NOT "), Bry_and = Bry_.new_a7(" AND "), Bry_or = Bry_.new_a7(" OR ");
|
||||
public static final Xosrh_qry_itm Null = new Xosrh_qry_itm(Tid_null, null, null, null);
|
||||
public static Xosrh_qry_itm nde_(byte tid, Xosrh_qry_itm lhs, Xosrh_qry_itm rhs) {return new Xosrh_qry_itm(tid, null, lhs, rhs);}
|
||||
public static Xosrh_qry_itm word_(byte[] src, Xosrh_qry_tkn word_tkn) {
|
||||
byte tid = word_tkn.Tid() == Xosrh_qry_tkn.Tid_word ? Xosrh_qry_itm.Tid_word : Xosrh_qry_itm.Tid_word_quote;
|
||||
return new Xosrh_qry_itm(tid, word_tkn.Val(src), null, null);
|
||||
}
|
||||
}
|
||||
class Xosrh_qry_ids {
|
||||
public Xosrh_qry_ids(boolean not, List_adp ids) {this.not = not; this.ids = ids;}
|
||||
public boolean Not() {return not;} public Xosrh_qry_ids Not_(boolean v) {not = v; return this;} private boolean not;
|
||||
public List_adp Ids() {return ids;} public Xosrh_qry_ids Ids_(List_adp v) {ids = v; return this;} List_adp ids = List_adp_.Noop;
|
||||
public static final Xosrh_qry_ids Null = new Xosrh_qry_ids(false, List_adp_.Noop);
|
||||
}
|
||||
44
400_xowa/src/gplx/xowa/specials/search/Xosrh_rslt_grp.java
Normal file
44
400_xowa/src/gplx/xowa/specials/search/Xosrh_rslt_grp.java
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.xowa.wikis.data.tbls.*;
|
||||
public class Xosrh_rslt_grp {
|
||||
public Xosrh_rslt_grp(int idx) {this.idx = idx;} private Xowd_page_itm[] itms = Xowd_page_itm.Ary_empty;
|
||||
public int Idx() {return idx;} private int idx;
|
||||
public int Itms_len() {return itms_len;} private int itms_len; int itms_max;
|
||||
public int Itms_total() {return itms_total;} public Xosrh_rslt_grp Itms_total_(int v) {itms_total = v; return this;} private int itms_total;
|
||||
public Xowd_page_itm Itms_get_at(int i) {return itms[i];}
|
||||
public void Itms_add(Xowd_page_itm itm) {
|
||||
int new_itms_len = itms_len + 1;
|
||||
if (new_itms_len > itms_max) {
|
||||
itms_max = itms_max == 0 ? 2 : itms_max * 2;
|
||||
itms = (Xowd_page_itm[])Array_.Resize(itms, itms_max);
|
||||
}
|
||||
itms[itms_len] = itm;
|
||||
itms_len = new_itms_len;
|
||||
}
|
||||
public boolean Itms_full() {return itms_len >= itms_max;}
|
||||
public void Itms_clear() {
|
||||
for (int i = 0; i < itms_len; i++)
|
||||
itms[i] = null;
|
||||
itms = Xowd_page_itm.Ary_empty;
|
||||
itms_len = itms_max = 0;
|
||||
}
|
||||
public void Itms_sort(Xowd_page_itm_sorter sorter) {Array_.Sort(itms, sorter);}
|
||||
public static final Xosrh_rslt_grp[] Ary_empty = new Xosrh_rslt_grp[0];
|
||||
}
|
||||
@@ -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.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.xowa.wikis.data.tbls.*;
|
||||
public class Xosrh_rslt_itm_sorter implements gplx.lists.ComparerAble {
|
||||
public byte Tid() {return tid;} public Xosrh_rslt_itm_sorter Tid_(byte v) {tid = v; return this;} private byte tid = Tid_len_dsc;
|
||||
public int compare(Object lhsObj, Object rhsObj) {
|
||||
Xowd_page_itm lhs = (Xowd_page_itm)lhsObj;
|
||||
Xowd_page_itm rhs = (Xowd_page_itm)rhsObj;
|
||||
if (lhs == null || rhs == null || tid == Tid_none) return CompareAble_.Same;
|
||||
// else if (lhs == null) return CompareAble_.Less;
|
||||
// else if (rhs == null) return CompareAble_.More;
|
||||
else {
|
||||
switch (tid) {
|
||||
case Tid_len_dsc: return Int_.Compare(lhs.Text_len(), rhs.Text_len()) * -1;
|
||||
case Tid_ttl_asc: return Bry_.Compare(lhs.Ttl_page_db(), rhs.Ttl_page_db());
|
||||
case Tid_id: return Int_.Compare(lhs.Id(), rhs.Id());
|
||||
default: throw Exc_.new_unhandled(tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
public static final byte Tid_none = 0, Tid_len_dsc = 1, Tid_ttl_asc = 2, Tid_id = 3;
|
||||
public static byte parse_(String v) {
|
||||
if (String_.Eq(v, "none")) return Tid_none;
|
||||
else if (String_.Eq(v, "len_desc")) return Tid_len_dsc;
|
||||
else if (String_.Eq(v, "title_asc")) return Tid_ttl_asc;
|
||||
else throw Exc_.new_unhandled(v);
|
||||
}
|
||||
public static String Xto_url_arg(byte v) {
|
||||
switch (v) {
|
||||
case Tid_none: return "";
|
||||
case Tid_len_dsc: return "&xowa_sort=len_desc";
|
||||
case Tid_ttl_asc: return "&xowa_sort=title_asc";
|
||||
default: throw Exc_.new_unhandled(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
153
400_xowa/src/gplx/xowa/specials/search/Xosrh_scanner.java
Normal file
153
400_xowa/src/gplx/xowa/specials/search/Xosrh_scanner.java
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.core.primitives.*; import gplx.core.btries.*;
|
||||
class Xosrh_scanner {
|
||||
List_adp tkns = List_adp_.new_(); byte[] src; int src_len; int pos; int txt_bgn;
|
||||
public Xosrh_qry_tkn[] Scan(byte[] src) {
|
||||
this.src = src; this.src_len = src.length;
|
||||
tkns.Clear(); pos = 0; txt_bgn = -1;
|
||||
while (pos < src_len) {
|
||||
byte cur_b = src[pos];
|
||||
Object cur_obj = trie.Match_bgn_w_byte(cur_b, src, pos, src_len);
|
||||
if (cur_obj == null) { // text character
|
||||
if (txt_bgn == -1) txt_bgn = pos; // 1st character not set; set it
|
||||
++pos;
|
||||
}
|
||||
else { // AND, OR, (, ), -, \s, "
|
||||
int pos_end = trie.Match_pos();
|
||||
byte cur_tid = ((Byte_obj_val)cur_obj).Val();
|
||||
if (Cur_join_is_word(cur_tid, pos_end)) continue;
|
||||
if (txt_bgn != -1) { // pending word; create
|
||||
Tkns_add_word(Xosrh_qry_tkn.Tid_word, txt_bgn, pos);
|
||||
txt_bgn = -1;
|
||||
}
|
||||
switch (cur_tid) {
|
||||
case Xosrh_qry_tkn.Tid_space: // discard spaces
|
||||
pos = Bry_finder.Find_fwd_while(src, pos, src_len, Byte_ascii.Space);
|
||||
break;
|
||||
case Xosrh_qry_tkn.Tid_quote: // find end quote and add as word
|
||||
int quote_bgn = pos + 1;
|
||||
int quote_end = Bry_finder.Find_fwd(src, Byte_ascii.Quote, quote_bgn, src_len);
|
||||
if (quote_end == Bry_.NotFound) throw Exc_.new_("could not find end quote", "src", String_.new_u8(src));
|
||||
Tkns_add_word(Xosrh_qry_tkn.Tid_word_quoted, quote_bgn, quote_end);
|
||||
pos = quote_end + 1; // +1 to place after quote
|
||||
break;
|
||||
case Xosrh_qry_tkn.Tid_not:
|
||||
Tkns_add_word(Xosrh_qry_tkn.Tid_not, pos, pos_end);
|
||||
pos = pos_end;
|
||||
break;
|
||||
case Xosrh_qry_tkn.Tid_paren_bgn: case Xosrh_qry_tkn.Tid_paren_end:
|
||||
case Xosrh_qry_tkn.Tid_and: case Xosrh_qry_tkn.Tid_or:
|
||||
tkns.Add(new_tkn_(cur_tid, pos, pos_end));
|
||||
pos = pos_end;
|
||||
break;
|
||||
default: throw Exc_.new_unhandled(cur_tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (txt_bgn != -1) { // pending word; create
|
||||
Tkns_add_word(Xosrh_qry_tkn.Tid_word, txt_bgn, pos);
|
||||
txt_bgn = -1;
|
||||
}
|
||||
return (Xosrh_qry_tkn[])tkns.To_ary_and_clear(Xosrh_qry_tkn.class);
|
||||
}
|
||||
boolean Cur_join_is_word(byte cur_tid, int pos_end) { // extra logic to handle and / or occuring in unquoted strings; EX: random; for
|
||||
switch (cur_tid) {
|
||||
default: return false; // only look at AND, OR, -
|
||||
case Xosrh_qry_tkn.Tid_and: case Xosrh_qry_tkn.Tid_or: case Xosrh_qry_tkn.Tid_not:
|
||||
break;
|
||||
}
|
||||
boolean join_is_word = true;
|
||||
if (txt_bgn == -1) { // no pending word;
|
||||
if (cur_tid == Xosrh_qry_tkn.Tid_not) return false; // NOT is only operator if no pending tkn; EX: -abc -> NOT abc; a-b -> a-b
|
||||
byte nxt_b = pos_end < src_len ? src[pos_end] : Byte_ascii.Nil;
|
||||
Object nxt_obj = trie.Match_bgn_w_byte(nxt_b, src, pos_end, src_len);
|
||||
if (nxt_obj == null) // next tkn is text; join must be word
|
||||
join_is_word = true;
|
||||
else { // next tkn is tkn
|
||||
byte nxt_tid = ((Byte_obj_val)nxt_obj).Val();
|
||||
switch (nxt_tid) {
|
||||
case Xosrh_qry_tkn.Tid_space: case Xosrh_qry_tkn.Tid_quote:
|
||||
case Xosrh_qry_tkn.Tid_paren_bgn: case Xosrh_qry_tkn.Tid_paren_end:
|
||||
join_is_word = false; // next tkn is sym; and/or is not word; EX: a AND ; a AND"b"; a AND(b)
|
||||
break;
|
||||
case Xosrh_qry_tkn.Tid_not: case Xosrh_qry_tkn.Tid_and: case Xosrh_qry_tkn.Tid_or:
|
||||
join_is_word = true; // next tkn is and or not; and/or is word; EX: andor; oror; or-abc;
|
||||
break;
|
||||
default: throw Exc_.new_unhandled(cur_tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // pending word; cur join must be word; EX: "grand": "and" invoked and "gr" pending
|
||||
join_is_word = true;
|
||||
}
|
||||
if (join_is_word) {
|
||||
if (txt_bgn == -1) txt_bgn = pos; // 1st character not set; set it
|
||||
pos = pos_end;
|
||||
return true;
|
||||
}
|
||||
if (txt_bgn != -1) {
|
||||
Tkns_add_word(Xosrh_qry_tkn.Tid_word, txt_bgn, pos); // create word
|
||||
txt_bgn = -1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private void Tkns_add_word(byte tid, int src_bgn, int src_end) {
|
||||
if (tkns.Count() > 0) { // at least 1 tkn
|
||||
Xosrh_qry_tkn last_tkn = (Xosrh_qry_tkn)tkns.Get_at_last();
|
||||
if (last_tkn.Tid() == Xosrh_qry_tkn.Tid_word) // previous tkn is not word; auto "AND" words; EX: A B -> A AND B
|
||||
tkns.Add(Xosrh_qry_tkn.new_bry_(Xosrh_qry_tkn.Tid_and, Bry_and));
|
||||
}
|
||||
if (tid == Xosrh_qry_tkn.Tid_word) { // if word has symbol, convert to quoted; EX: a-b should become "a-b"; otherwise searcher would search for a single word a-b
|
||||
byte[] cur_word = Bry_.Mid(src, src_bgn, src_end);
|
||||
byte[][] words = gplx.xowa.bldrs.cmds.texts.Xob_search_base.Split_ttl_into_words(null, tmp_list, tmp_bfr, cur_word);
|
||||
int words_len = words.length;
|
||||
if (words_len == 1 && !Bry_.Eq(words[0], cur_word) && Bry_finder.Find_fwd(cur_word, Byte_ascii.Star) == -1) {
|
||||
tkns.Add(Xosrh_qry_tkn.new_bry_(tid, words[0]));
|
||||
return;
|
||||
}
|
||||
if (words.length > 1)
|
||||
tid = Xosrh_qry_tkn.Tid_word_quoted;
|
||||
}
|
||||
tkns.Add(new_tkn_(tid, src_bgn, src_end));
|
||||
}
|
||||
Ordered_hash tmp_list = Ordered_hash_.new_(); Bry_bfr tmp_bfr = Bry_bfr.new_();
|
||||
Xosrh_qry_tkn new_tkn_(byte tid, int val_bgn, int val_end) {return Xosrh_qry_tkn.new_pos_(tid, val_bgn, val_end);}
|
||||
private static byte[] Bry_and = Bry_.new_a7("AND");
|
||||
private static final Btrie_slim_mgr trie = Btrie_slim_mgr.ci_ascii_()// NOTE:ci.ascii:OR / AND only
|
||||
.Add_str_byte(" ", Xosrh_qry_tkn.Tid_space)
|
||||
.Add_str_byte("\"", Xosrh_qry_tkn.Tid_quote)
|
||||
.Add_str_byte("-", Xosrh_qry_tkn.Tid_not)
|
||||
.Add_str_byte("(", Xosrh_qry_tkn.Tid_paren_bgn)
|
||||
.Add_str_byte(")", Xosrh_qry_tkn.Tid_paren_end)
|
||||
.Add_str_byte("or", Xosrh_qry_tkn.Tid_or)
|
||||
.Add_str_byte("and", Xosrh_qry_tkn.Tid_and);
|
||||
public static final Xosrh_scanner _ = new Xosrh_scanner(); Xosrh_scanner() {}
|
||||
}
|
||||
class Xosrh_qry_tkn {
|
||||
Xosrh_qry_tkn(byte tid, int val_bgn, int val_end, byte[] val_bry) {this.tid = tid; this.val_bgn = val_bgn; this.val_end = val_end; this.val_bry = val_bry;}
|
||||
public byte Tid() {return tid;} private byte tid;
|
||||
int val_bgn = -1;
|
||||
int val_end = -1;
|
||||
byte[] val_bry;
|
||||
public byte[] Val(byte[] src) {return val_bry == null ? Bry_.Mid(src, val_bgn, val_end) : val_bry;}
|
||||
public static Xosrh_qry_tkn new_pos_(byte tid, int val_bgn, int val_end) {return new Xosrh_qry_tkn(tid, val_bgn, val_end, null);}
|
||||
public static Xosrh_qry_tkn new_bry_(byte tid, byte[] val_bry) {return new Xosrh_qry_tkn(tid, -1, -1, val_bry);}
|
||||
public static final byte Tid_root = 1, Tid_word = 2, Tid_word_quoted = 3, Tid_space = 4, Tid_quote = 5, Tid_not = 6, Tid_paren_bgn = 7, Tid_paren_end = 8, Tid_or = 9, Tid_and = 10, Tid_eos = 11;
|
||||
}
|
||||
@@ -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.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.core.primitives.*; import gplx.xowa.wikis.*; import gplx.xowa.langs.*;
|
||||
import gplx.xowa.wikis.domains.crts.*;
|
||||
class Xow_domain_sorter__manual implements gplx.lists.ComparerAble {
|
||||
private final Xow_domain cur_domain;
|
||||
private final Xow_domain_crt_itm[] ary; private final int ary_len;
|
||||
public Xow_domain_sorter__manual(Xow_domain cur_domain, Xow_domain_crt_itm[] ary) {
|
||||
this.cur_domain = cur_domain; this.ary = ary; this.ary_len = ary.length;
|
||||
}
|
||||
public int compare(Object lhsObj, Object rhsObj) {
|
||||
Xow_domain lhs = (Xow_domain)lhsObj;
|
||||
Xow_domain rhs = (Xow_domain)rhsObj;
|
||||
int lhs_sort = Get_sort_idx_or_neg1(lhs);
|
||||
int rhs_sort = Get_sort_idx_or_neg1(rhs);
|
||||
if (lhs_sort == -1 && rhs_sort != -1) return rhs_sort;
|
||||
else if (lhs_sort != -1 && rhs_sort == -1) return lhs_sort;
|
||||
else if (lhs_sort != -1 && rhs_sort != -1) return Int_.Compare(lhs_sort, rhs_sort);
|
||||
else return Bry_.Compare(lhs.Domain_bry(), rhs.Domain_bry());
|
||||
}
|
||||
private int Get_sort_idx_or_neg1(Xow_domain domain) {
|
||||
int sort_idx = domain.Sort_idx(); if (sort_idx != -1) return sort_idx;
|
||||
sort_idx = Int_.MaxValue;
|
||||
for (int i = 0; i < ary_len; ++i) {
|
||||
Xow_domain_crt_itm crt = ary[i];
|
||||
if (crt.Matches(cur_domain, domain)) {sort_idx = i; break;}
|
||||
}
|
||||
domain.Sort_idx_(sort_idx);
|
||||
return sort_idx;
|
||||
}
|
||||
public static void Sort(Xow_domain_sorter__manual sorter, Xow_domain[] ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i)
|
||||
ary[i].Sort_idx_(-1);
|
||||
Array_.Sort(ary, sorter);
|
||||
}
|
||||
}
|
||||
class Xow_domain_sorter__manual_tid implements gplx.lists.ComparerAble {
|
||||
private final Hash_adp sort_hash = Hash_adp_.new_(); private final Int_obj_ref sort_key = Int_obj_ref.neg1_();
|
||||
public Xow_domain_sorter__manual_tid(int[] id_ary) {
|
||||
int len = id_ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
int id_itm = id_ary[i];
|
||||
sort_hash.Add_if_dupe_use_nth(Int_obj_ref.new_(id_itm), Int_obj_ref.new_(i));
|
||||
}
|
||||
}
|
||||
public int compare(Object lhsObj, Object rhsObj) {
|
||||
Xow_domain lhs = (Xow_domain)lhsObj;
|
||||
Xow_domain rhs = (Xow_domain)rhsObj;
|
||||
int lhs_sort = Get_sort_idx_or_neg1(lhs.Domain_tid());
|
||||
int rhs_sort = Get_sort_idx_or_neg1(rhs.Domain_tid());
|
||||
if (lhs_sort == -1 && rhs_sort != -1) return rhs_sort;
|
||||
else if (lhs_sort != -1 && rhs_sort == -1) return lhs_sort;
|
||||
else if (lhs_sort != -1 && rhs_sort != -1) return Int_.Compare(lhs_sort, rhs_sort);
|
||||
else return Bry_.Compare(Xow_domain_type_.Get_type_as_bry(lhs.Domain_tid()), Xow_domain_type_.Get_type_as_bry(rhs.Domain_tid()));
|
||||
}
|
||||
private int Get_sort_idx_or_neg1(int tid) {
|
||||
Object o = sort_hash.Get_by(sort_key.Val_(tid));
|
||||
return o == null ? -1 : ((Int_obj_ref)o).Val();
|
||||
}
|
||||
public static Xow_domain_sorter__manual_tid new_(byte[]... id_brys) {
|
||||
int len = id_brys.length;
|
||||
int[] id_ints = new int[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
byte[] id_bry = id_brys[i];
|
||||
int id_int = Xow_domain_type_.Get_type_as_tid(id_bry);
|
||||
id_ints[i] = id_int;
|
||||
}
|
||||
return new Xow_domain_sorter__manual_tid(id_ints);
|
||||
}
|
||||
}
|
||||
class Xow_domain_sorter__manual_lang implements gplx.lists.ComparerAble {
|
||||
private final Hash_adp sort_hash = Hash_adp_.new_(); private final Int_obj_ref sort_key = Int_obj_ref.neg1_();
|
||||
public Xow_domain_sorter__manual_lang(int[] id_ary) {
|
||||
int len = id_ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
int id_int = id_ary[i];
|
||||
sort_hash.Add_if_dupe_use_nth(Int_obj_ref.new_(id_int), Int_obj_ref.new_(i));
|
||||
}
|
||||
}
|
||||
public int compare(Object lhsObj, Object rhsObj) {
|
||||
Xow_domain lhs = (Xow_domain)lhsObj;
|
||||
Xow_domain rhs = (Xow_domain)rhsObj;
|
||||
int lhs_sort = Get_sort_idx_or_neg1(lhs.Lang_uid());
|
||||
int rhs_sort = Get_sort_idx_or_neg1(rhs.Lang_uid());
|
||||
if (lhs_sort == -1 && rhs_sort != -1) return rhs_sort;
|
||||
else if (lhs_sort != -1 && rhs_sort == -1) return lhs_sort;
|
||||
else if (lhs_sort != -1 && rhs_sort != -1) return Int_.Compare(lhs_sort, rhs_sort);
|
||||
else return Bry_.Compare(lhs.Lang_key(), rhs.Lang_key());
|
||||
}
|
||||
private int Get_sort_idx_or_neg1(int tid) {
|
||||
Object o = sort_hash.Get_by(sort_key.Val_(tid));
|
||||
return o == null ? -1 : ((Int_obj_ref)o).Val();
|
||||
}
|
||||
public static Xow_domain_sorter__manual_lang new_(byte[]... id_brys) {
|
||||
int len = id_brys.length;
|
||||
int[] id_ints = new int[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
byte[] id_bry = id_brys[i];
|
||||
int id_int = Xol_lang_itm_.Get_by_key_or_intl(id_bry).Id();
|
||||
id_ints[i] = id_int;
|
||||
}
|
||||
return new Xow_domain_sorter__manual_lang(id_ints);
|
||||
}
|
||||
}
|
||||
74
400_xowa/src/gplx/xowa/specials/search/Xows_arg_mgr.java
Normal file
74
400_xowa/src/gplx/xowa/specials/search/Xows_arg_mgr.java
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.core.primitives.*;
|
||||
class Xows_arg_mgr {
|
||||
private final Xows_paging_parser paging_parser = new Xows_paging_parser();
|
||||
public Xows_ns_mgr Ns_mgr() {return ns_mgr;} private final Xows_ns_mgr ns_mgr = new Xows_ns_mgr();
|
||||
public byte[] Search_bry() {return search_bry;} private byte[] search_bry;
|
||||
public int Paging_idx() {return paging_idx;} private int paging_idx;
|
||||
public byte Sort_tid() {return sort_tid;} private byte sort_tid;
|
||||
public byte[] Cancel() {return cancel;} private byte[] cancel;
|
||||
public Xows_paging_itm[] Paging_itms() {return paging_itms;} private Xows_paging_itm[] paging_itms;
|
||||
public Xows_arg_mgr Search_bry_(byte[] v) {search_bry = v; return this;}
|
||||
public Xows_arg_mgr Clear() {
|
||||
ns_mgr.Clear();
|
||||
this.search_bry = null;
|
||||
this.paging_idx = 0;
|
||||
this.sort_tid = Xosrh_rslt_itm_sorter.Tid_none;
|
||||
this.cancel = null;
|
||||
return this;
|
||||
}
|
||||
public void Parse(Gfo_url_arg[] arg_ary) {
|
||||
if (arg_ary == null) return;
|
||||
int len = arg_ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Gfo_url_arg arg = arg_ary[i];
|
||||
byte[] key = arg.Key_bry();
|
||||
Object tid = url_args.Get_by(key);
|
||||
if (tid != null) {
|
||||
switch (((Byte_obj_val)tid).Val()) {
|
||||
case Arg_search: this.search_bry = Bry_.Replace(arg.Val_bry(), Byte_ascii.Plus, Byte_ascii.Space); break;
|
||||
case Arg_page_idx: this.paging_idx = Bry_.Xto_int_or(arg.Val_bry(), 0); break;
|
||||
case Arg_sort: this.sort_tid = Xosrh_rslt_itm_sorter.parse_(String_.new_a7(arg.Val_bry())); break;
|
||||
case Arg_cancel: this.cancel = arg.Val_bry(); break;
|
||||
case Arg_paging: this.paging_itms = paging_parser.Parse(arg.Val_bry()); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (Bry_.Has_at_bgn(key, Ns_bry)) // check for ns*; EX: &ns0=1&ns8=1; NOTE: lowercase only
|
||||
ns_mgr.Add_by_parse(key, arg.Val_bry());
|
||||
}
|
||||
}
|
||||
ns_mgr.Add_main_if_empty();
|
||||
}
|
||||
private static final byte Arg_search = 0, Arg_page_idx = 1, Arg_sort = 2, Arg_cancel = 3, Arg_paging = 4;
|
||||
private static byte[] Ns_bry = Bry_.new_a7("ns");
|
||||
public static final byte[]
|
||||
Arg_bry_page_index = Bry_.new_a7("xowa_page_index")
|
||||
, Arg_bry_cancel = Bry_.new_a7("cancel")
|
||||
;
|
||||
private static final Hash_adp_bry url_args = Hash_adp_bry.ci_ascii_()
|
||||
.Add_str_byte("xowa_paging", Arg_paging)
|
||||
.Add_bry_byte(Arg_bry_page_index, Arg_page_idx)
|
||||
.Add_str_byte("xowa_sort", Arg_sort)
|
||||
.Add_str_byte("search", Arg_search)
|
||||
.Add_bry_byte(Arg_bry_cancel, Arg_cancel)
|
||||
;
|
||||
}
|
||||
86
400_xowa/src/gplx/xowa/specials/search/Xows_core.java
Normal file
86
400_xowa/src/gplx/xowa/specials/search/Xows_core.java
Normal file
@@ -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.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.dbs.*; import gplx.xowa.wikis.*; import gplx.xowa.wikis.data.*;
|
||||
class Xows_core {
|
||||
private final Xoae_wiki_mgr wiki_mgr;
|
||||
private final Hash_adp_bry cache_hash = Hash_adp_bry.cs_(); private final Hash_adp_bry cmd_hash = Hash_adp_bry.cs_();
|
||||
private boolean ask_for_upgrade = true; private final Hash_adp_bry upgraded_wikis = Hash_adp_bry.cs_();
|
||||
public Xows_core(Xoae_wiki_mgr wiki_mgr) {this.wiki_mgr = wiki_mgr;}
|
||||
private final Xows_html_wkr html_wkr = new Xows_html_wkr();
|
||||
public Xows_db_cache Get_cache_or_new(byte[] key) {
|
||||
Xows_db_cache cache = (Xows_db_cache)cache_hash.Get_by_bry(key);
|
||||
if (cache == null) {
|
||||
cache = new Xows_db_cache();
|
||||
cache_hash.Add_bry_obj(key, cache);
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
public void Search(Xow_wiki search_wiki, Xoae_page page, Xows_ui_qry qry) {
|
||||
// generate 1 cmd per wiki
|
||||
Xow_domain[] domain_ary = qry.Wiki_domains(); int domain_ary_len = domain_ary.length;
|
||||
for (int i = 0; i < domain_ary_len; ++i) {
|
||||
Xow_domain domain = domain_ary[i];
|
||||
try {
|
||||
Xowe_wiki wiki = wiki_mgr.Get_by_key_or_make(domain.Domain_bry()); wiki.Init_assert();
|
||||
Assert_page_count(wiki);
|
||||
Xows_ui_cmd cmd = new Xows_ui_cmd(this, qry, wiki, page, page.Tab_data().Close_mgr(), page.Tab_data().Tab().Html_itm());
|
||||
qry.Cmds__add(cmd);
|
||||
} catch (Exception e) {Xoa_app_.Usr_dlg().Warn_many("", "", "search:wiki failed; wiki=~{0} err=~{1}", domain.Domain_str(), Err_.Message_lang(e));} // handle bad wikis, like "en.wikipedia.org-old"; DATE:2015-04-24
|
||||
}
|
||||
qry.Page_max_(Int_.MaxValue);
|
||||
// do search and generate html
|
||||
html_wkr.Init_by_wiki(search_wiki, search_wiki.Lang().Num_mgr(), qry);
|
||||
int cmds_len = qry.Cmds__len();
|
||||
Bry_bfr tmp_bfr = Bry_bfr.new_();
|
||||
for (int i = 0; i < cmds_len; ++i) {
|
||||
Xows_ui_cmd cmd = qry.Cmds__get_at(i); byte[] cmd_key = cmd.Key();
|
||||
cmd_hash.Add_if_dupe_use_nth(cmd_key, cmd);
|
||||
boolean searching_db = cmd.Search();
|
||||
html_wkr.Gen_tbl(tmp_bfr, cmd.Rslt(), cmd_key, cmd.Wiki().Domain_bry(), searching_db);
|
||||
}
|
||||
page.Data_raw_(html_wkr.Gen_page(tmp_bfr.Xto_bry_and_clear()));
|
||||
}
|
||||
public void Search_end(Xows_ui_cmd cmd) {
|
||||
cmd_hash.Del(cmd.Key());
|
||||
}
|
||||
public void Cancel(byte[] cmd_key) {
|
||||
Xows_ui_cmd cmd = (Xows_ui_cmd)cmd_hash.Get_by_bry(cmd_key);
|
||||
if (cmd == null) return;
|
||||
cmd.Cancel();
|
||||
cmd_hash.Del(cmd.Key());
|
||||
}
|
||||
private void Assert_page_count(Xowe_wiki wiki) {
|
||||
Xowd_db_file search_db = wiki.Data__core_mgr().Db__search();
|
||||
if (ask_for_upgrade
|
||||
&& wiki.App().App_type().Uid_is_gui()
|
||||
&& !search_db.Tbl__search_word().Ddl__page_count()
|
||||
&& !upgraded_wikis.Has(wiki.Domain_bry()) ) {
|
||||
ask_for_upgrade = false;
|
||||
upgraded_wikis.Add_as_key_and_val(wiki.Domain_bry());
|
||||
boolean ok = wiki.Appe().Gui_mgr().Kit().Ask_ok_cancel("", "", String_.Concat_lines_nl_skip_last
|
||||
( "XOWA would like to upgrade your search database for " + wiki.Domain_str() + "."
|
||||
, "* Press OK to upgrade. This may take a few minutes."
|
||||
, "* Press Cancel to skip. You will be able to search, but the results may be slower for multi-word searches (EX: 'The Earth')."
|
||||
, "If you cancel, XOWA will ask you to upgrade this wiki again next time you restart the application."
|
||||
));
|
||||
if (ok)
|
||||
search_db.Tbl__search_word().Ddl__page_count__add(search_db.Tbl__search_link(), search_db.Tbl__cfg());
|
||||
}
|
||||
}
|
||||
}
|
||||
42
400_xowa/src/gplx/xowa/specials/search/Xows_db_cache.java
Normal file
42
400_xowa/src/gplx/xowa/specials/search/Xows_db_cache.java
Normal file
@@ -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.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.xowa.specials.search.parsers_old.*;
|
||||
class Xows_db_cache { // one cache per search term; EX: "Earth* AND (History OR Future) AND -"middle earth"" is one cache
|
||||
private final Ordered_hash hash = Ordered_hash_.new_bry_();
|
||||
public Xows_db_word[] Words() {return words;} private Xows_db_word[] words; // words in cache; EX: earth, history, future but not "middle earth" (since not'ed)
|
||||
public Xows_db_matcher Matcher() {return matcher;} private Xows_db_matcher matcher; // criteria
|
||||
public boolean Done() {return done;} public void Done_y_() {done = true;} private boolean done; // marks if db search is done
|
||||
public int Count() {return hash.Count();}
|
||||
public int Itms_end() {return itms_end;} public void Itms_end_(int v) {itms_end = v;} private int itms_end;
|
||||
public void Init_by_db(Cancelable cxl, byte[] raw, gplx.xowa.wikis.data.tbls.Xowd_search_word_tbl word_tbl) {
|
||||
this.matcher = new Xow_search_parser().Parse(raw);
|
||||
this.words = new Xows_db_matcher_bldr().Gather_words_for_db(cxl, matcher, word_tbl);
|
||||
}
|
||||
public boolean Has(byte[] key) {return hash.Has(key);}
|
||||
public Xows_db_row Get_at(int i) {return (Xows_db_row)hash.Get_at(i);}
|
||||
public void Add(Xows_db_row row) {hash.Add(row.Page_ttl().Full_db(), row);}
|
||||
public void Get_between(Xows_ui_rslt search_ui, int bgn, int end) {
|
||||
if (bgn >= hash.Count()) return; // requested start not in cache; exit
|
||||
for (int i = bgn; i < end; ++i) {
|
||||
if (i >= hash.Count()) break;
|
||||
search_ui.Add((Xows_db_row)hash.Get_at(i));
|
||||
}
|
||||
}
|
||||
public void Sort() {hash.Sort_by(Xows_db_row_sorter.Page_len_dsc);}
|
||||
}
|
||||
68
400_xowa/src/gplx/xowa/specials/search/Xows_db_matcher.java
Normal file
68
400_xowa/src/gplx/xowa/specials/search/Xows_db_matcher.java
Normal file
@@ -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.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.core.regxs.*;
|
||||
public class Xows_db_matcher {
|
||||
private final Gfo_pattern raw_pattern;
|
||||
public Xows_db_matcher(int tid, byte[] raw, Xows_db_matcher lhs, Xows_db_matcher rhs) {
|
||||
this.tid = tid; this.raw = raw; this.lhs = lhs; this.rhs = rhs;
|
||||
this.raw_pattern = Bry_.Has(raw, Byte_ascii.Star) ? new Gfo_pattern(raw) : null;
|
||||
}
|
||||
public int Tid() {return tid;} private final int tid;
|
||||
public int Page_count() {return page_count;} public void Page_count_(int v) {page_count = v;} private int page_count;
|
||||
public byte[] Raw() {return raw;} private final byte[] raw;
|
||||
public Xows_db_matcher Lhs() {return lhs;} private final Xows_db_matcher lhs;
|
||||
public Xows_db_matcher Rhs() {return rhs;} private final Xows_db_matcher rhs;
|
||||
public boolean Matches(byte[] page_ttl_lc, byte[][] page_ttl_words) {
|
||||
switch (tid) {
|
||||
case Xows_db_matcher.Tid_word: {
|
||||
int len = page_ttl_words.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
byte[] word = page_ttl_words[i];
|
||||
if (raw_pattern == null) {
|
||||
if (Bry_.Eq(word, raw)) return true;
|
||||
}
|
||||
else {
|
||||
if (raw_pattern.Match(word)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case Xows_db_matcher.Tid_word_quote: // note that raw does not have quotes; EX: "B*" -> B*
|
||||
return Bry_finder.Find_fwd(page_ttl_lc, raw) != Bry_finder.Not_found;
|
||||
case Xows_db_matcher.Tid_not:
|
||||
return !rhs.Matches(page_ttl_lc, page_ttl_words);
|
||||
case Xows_db_matcher.Tid_or:
|
||||
return lhs.Matches(page_ttl_lc, page_ttl_words) || rhs.Matches(page_ttl_lc, page_ttl_words);
|
||||
case Xows_db_matcher.Tid_and:
|
||||
return lhs.Matches(page_ttl_lc, page_ttl_words) && rhs.Matches(page_ttl_lc, page_ttl_words);
|
||||
case Xows_db_matcher.Tid_null: return false;
|
||||
default: throw Exc_.new_unhandled(tid);
|
||||
}
|
||||
}
|
||||
public static final Xows_db_matcher Null = new Xows_db_matcher(Xows_db_matcher.Tid_null, null, null, null);
|
||||
public static Xows_db_matcher new_join(byte tid, Xows_db_matcher lhs, Xows_db_matcher rhs) {return new Xows_db_matcher(tid, null, lhs, rhs);}
|
||||
public static final int
|
||||
Tid_word = 0
|
||||
, Tid_and = 1
|
||||
, Tid_or = 2
|
||||
, Tid_not = 3
|
||||
, Tid_word_quote = 4
|
||||
, Tid_null = 5
|
||||
;
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.xowa.wikis.data.tbls.*;
|
||||
class Xows_db_matcher_bldr {
|
||||
public Xows_db_word[] Gather_words_for_db(Cancelable cxl, Xows_db_matcher matcher, Xowd_search_word_tbl word_tbl) {
|
||||
List_adp rv = List_adp_.new_();
|
||||
Gather_words_for_db(cxl, matcher, rv, word_tbl);
|
||||
rv.Sort_by(Xows_db_word_sorter.Page_count_dsc);
|
||||
return (Xows_db_word[])rv.To_ary(Xows_db_word.class);
|
||||
}
|
||||
private void Gather_words_for_db(Cancelable cxl, Xows_db_matcher matcher, List_adp rv, Xowd_search_word_tbl word_tbl) {
|
||||
switch (matcher.Tid()) {
|
||||
case Xows_db_matcher.Tid_word:
|
||||
byte[] word_text = matcher.Raw();
|
||||
if (Bry_.Has(word_text, Byte_ascii.Star))
|
||||
Load_word_many(cxl, rv, word_text, word_tbl);
|
||||
else
|
||||
Load_word_one(rv, word_text, word_tbl);
|
||||
break;
|
||||
case Xows_db_matcher.Tid_word_quote:
|
||||
List_adp tmp = List_adp_.new_();
|
||||
byte[][] words = Bry_.Split(matcher.Raw(), Byte_ascii.Space, Bool_.Y);
|
||||
int words_len = words.length;
|
||||
for (int i = 0; i < words_len; ++i) {
|
||||
byte[] word = words[i];
|
||||
Load_word_one(tmp, word, word_tbl);
|
||||
}
|
||||
if (tmp.Count() == 0) return; // no words in db; EX: "xyz cba"
|
||||
tmp.Sort_by(Xows_db_word_sorter.Page_count_dsc);
|
||||
rv.Add(tmp.Get_at(0)); // add lowest page_count word to db; EX: search for "earth and" should search for "earth" only, but match for "earth and"
|
||||
break;
|
||||
case Xows_db_matcher.Tid_and:
|
||||
List_adp lhs_tmp = List_adp_.new_(), rhs_tmp = List_adp_.new_();
|
||||
Gather_words_for_db(cxl, matcher.Lhs(), lhs_tmp, word_tbl);
|
||||
Gather_words_for_db(cxl, matcher.Rhs(), rhs_tmp, word_tbl);
|
||||
List_adp_.Add_list(rv, Calc_lowest(lhs_tmp, rhs_tmp)); // calc side with lowest count; add to rv;
|
||||
break;
|
||||
case Xows_db_matcher.Tid_or:
|
||||
Gather_words_for_db(cxl, matcher.Lhs(), rv, word_tbl);
|
||||
Gather_words_for_db(cxl, matcher.Rhs(), rv, word_tbl);
|
||||
break;
|
||||
case Xows_db_matcher.Tid_not: break; // never add "NOT" to db_search
|
||||
case Xows_db_matcher.Tid_null: break; // should not happen
|
||||
default: throw Exc_.new_unhandled(matcher.Tid());
|
||||
}
|
||||
}
|
||||
private List_adp Calc_lowest(List_adp lhs, List_adp rhs) {
|
||||
int lhs_count = Calc(lhs);
|
||||
int rhs_count = Calc(rhs);
|
||||
// never return 0 as lowest count; note that NOT will return 0;
|
||||
if (lhs_count == 0) return rhs;
|
||||
else if (rhs_count == 0) return lhs;
|
||||
else return lhs_count < rhs_count ? lhs : rhs;
|
||||
}
|
||||
private int Calc(List_adp list) {
|
||||
int rv = 0;
|
||||
int len = list.Count();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Xows_db_word word = (Xows_db_word)list.Get_at(i);
|
||||
rv += word.Page_count();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private void Load_word_one(List_adp rv, byte[] word_text, Xowd_search_word_tbl word_tbl) {
|
||||
Xoa_app_.Usr_dlg().Prog_many("", "", "search:word by text; word=~{0}", word_text);
|
||||
Xowd_search_word_row row = word_tbl.Select_by_or_null(word_text); if (row == Xowd_search_word_row.Null) return;
|
||||
Xows_db_word word = new Xows_db_word(row.Id(), row.Text(), row.Page_count());
|
||||
rv.Add(word);
|
||||
}
|
||||
private void Load_word_many(Cancelable cxl, List_adp rv, byte[] word_text, Xowd_search_word_tbl word_tbl) {
|
||||
Xoa_app_.Usr_dlg().Prog_many("", "", "search:word by wildcard; word=~{0}", word_text);
|
||||
Xowd_search_word_row[] rows = word_tbl.Select_in(cxl, word_text);
|
||||
int len = rows.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Xowd_search_word_row row = rows[i];
|
||||
rv.Add(new Xows_db_word(row.Id(), row.Text(), row.Page_count()));
|
||||
}
|
||||
}
|
||||
}
|
||||
41
400_xowa/src/gplx/xowa/specials/search/Xows_db_row.java
Normal file
41
400_xowa/src/gplx/xowa/specials/search/Xows_db_row.java
Normal file
@@ -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.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
public class Xows_db_row {
|
||||
public Xows_db_row(byte[] wiki_domain, Xoa_ttl page_ttl, int page_id, int page_len) {
|
||||
this.wiki_domain = wiki_domain;
|
||||
this.page_ttl = page_ttl;
|
||||
this.page_id = page_id;
|
||||
this.page_len = page_len;
|
||||
this.key = Bry_.Add(wiki_domain, Byte_ascii.Pipe_bry, page_ttl.Full_db());
|
||||
}
|
||||
public byte[] Key() {return key;} private final byte[] key;
|
||||
public byte[] Wiki_domain() {return wiki_domain;} private final byte[] wiki_domain;
|
||||
public Xoa_ttl Page_ttl() {return page_ttl;} private final Xoa_ttl page_ttl;
|
||||
public int Page_id() {return page_id;} private final int page_id;
|
||||
public int Page_len() {return page_len;} private final int page_len;
|
||||
public static Xows_db_row[] Ary(Xows_db_row... v) {return v;}
|
||||
}
|
||||
class Xows_db_row_sorter implements gplx.lists.ComparerAble {
|
||||
public int compare(Object lhsObj, Object rhsObj) {
|
||||
Xows_db_row lhs = (Xows_db_row)lhsObj;
|
||||
Xows_db_row rhs = (Xows_db_row)rhsObj;
|
||||
return -Int_.Compare(lhs.Page_len(), rhs.Page_len());
|
||||
}
|
||||
public static final Xows_db_row_sorter Page_len_dsc = new Xows_db_row_sorter(); Xows_db_row_sorter() {}
|
||||
}
|
||||
109
400_xowa/src/gplx/xowa/specials/search/Xows_db_wkr.java
Normal file
109
400_xowa/src/gplx/xowa/specials/search/Xows_db_wkr.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.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.core.primitives.*; import gplx.dbs.*;
|
||||
import gplx.xowa.wikis.data.*; import gplx.xowa.wikis.data.tbls.*; import gplx.xowa.langs.cases.*;
|
||||
import gplx.gfui.*;
|
||||
class Xows_db_wkr {
|
||||
public void Search(Xows_ui_cmd cmd, Xows_ui_qry qry, Xows_ui_rslt rslt, Xows_db_cache cache, Xow_wiki wiki) {
|
||||
// assert matcher
|
||||
Xowd_db_file search_db = wiki.Data__core_mgr().Db__search();
|
||||
Xoa_app_.Usr_dlg().Prog_many("", "", "search started (please wait)");
|
||||
Xows_db_matcher matcher = cache.Matcher();
|
||||
if (matcher == null) {
|
||||
cache.Init_by_db
|
||||
( cmd
|
||||
, wiki.Lang().Case_mgr().Case_build_lower(qry.Search_raw()) // lower-case search
|
||||
, search_db.Tbl__search_word()
|
||||
);
|
||||
matcher = cache.Matcher();
|
||||
}
|
||||
// init
|
||||
int rslts_wanted = qry.Itms_end() - qry.Itms_bgn();
|
||||
Xowd_db_file core_db = wiki.Data__core_mgr().Db__core();
|
||||
Xowd_page_tbl page_tbl = core_db.Tbl__page();
|
||||
Xowd_search_link_tbl link_tbl = search_db.Tbl__search_link();
|
||||
Xows_db_word[] word_ary = cache.Words(); int word_ary_len = word_ary.length;
|
||||
// read pages for each word from db
|
||||
Db_attach_rdr attach_rdr = new Db_attach_rdr(search_db.Conn(), "page_db", core_db.Url());
|
||||
attach_rdr.Attach();
|
||||
int total_found = 0;
|
||||
try {
|
||||
while (true) {
|
||||
boolean found_none = true;
|
||||
for (int i = 0; i < word_ary_len; ++i) { // loop each word to get rslts_wanted
|
||||
if (cmd.Canceled()) return;
|
||||
Xows_db_word word = word_ary[i];
|
||||
if (word.Rslts_done()) continue; // last db_search for word returned 0 results; don't search again;
|
||||
int offset = word.Rslts_offset();
|
||||
Xoa_app_.Usr_dlg().Prog_many("", "", "searching; wiki=~{0} total=~{1} offset=~{2} index=~{3} word=~{4}", wiki.Domain_str(), word_ary_len, offset, i, word.Text());
|
||||
String sql = String_.Format(Search_sql, link_tbl.Tbl_name(), link_tbl.Fld_page_id(), link_tbl.Fld_word_id(), word.Id(), "page_len", "DESC", Int_.MaxValue, offset); // need to return enough results to fill qry.Page_len() as many results may be discarded below; DATE:2015-04-24
|
||||
int rslts_found = Search_pages(cmd, qry, rslt, cache, wiki, page_tbl, attach_rdr, sql, word, matcher, rslts_wanted);
|
||||
total_found += rslts_found;
|
||||
if (rslts_found == -1) return; // canceled
|
||||
else if (rslts_found > 0) found_none = false; // NOTE: do not reverse and do rslts_found == 0; want to check if any word returns results;
|
||||
}
|
||||
if (found_none) {cache.Done_y_(); break;}
|
||||
if (total_found >= rslts_wanted) break;
|
||||
}
|
||||
cache.Itms_end_(qry.Itms_end());
|
||||
cache.Sort();
|
||||
} finally {attach_rdr.Detach();}
|
||||
}
|
||||
private int Search_pages(Xows_ui_cmd cmd, Xows_ui_qry qry, Xows_ui_rslt rslt, Xows_db_cache cache, Xow_wiki wiki, Xowd_page_tbl page_tbl, Db_attach_rdr attach_rdr, String sql, Xows_db_word word, Xows_db_matcher matcher, int rslts_wanted) {
|
||||
int rslts_found = 0;
|
||||
Xow_ns_mgr ns_mgr = wiki.Ns_mgr(); Xol_case_mgr case_mgr = wiki.Lang().Case_mgr();
|
||||
Db_rdr rdr = attach_rdr.Exec_as_rdr(sql);
|
||||
try {
|
||||
while (rdr.Move_next()) {
|
||||
if (cmd.Canceled()) return -1;
|
||||
word.Rslts_offset_add_1();
|
||||
int page_ns = rdr.Read_int(page_tbl.Fld_page_ns());
|
||||
if (!qry.Ns_mgr().Has(page_ns)) continue; // ignore: ns doesn't match
|
||||
byte[] page_ttl = rdr.Read_bry_by_str(page_tbl.Fld_page_title());
|
||||
// Io_mgr.I.AppendFilStr("C:\\temp.txt", String_.new_u8(word.Text()) + "|" + Int_.Xto_str(page_ns) + "|" + String_.new_u8(page_ttl) + "\n");
|
||||
byte[] page_ttl_lc = case_mgr.Case_build_lower(Xoa_ttl.Replace_unders(page_ttl));
|
||||
byte[][] page_ttl_words = Bry_.Split(page_ttl_lc, Byte_ascii.Space, Bool_.Y);
|
||||
if (!matcher.Matches(page_ttl_lc, page_ttl_words)) continue; // ignore: ttl doesn't match matcher
|
||||
int page_id = rdr.Read_int(page_tbl.Fld_page_id());
|
||||
int page_len = rdr.Read_int(page_tbl.Fld_page_len());
|
||||
Xow_ns ns = ns_mgr.Ids_get_or_null(page_ns);
|
||||
byte[] page_ttl_w_ns = ns.Gen_ttl(page_ttl);
|
||||
if (cache.Has(page_ttl_w_ns)) continue; // ignore: page already added by another word; EX: "A B"; word is "B", but "A B" already added by "A"
|
||||
Xoa_ttl ttl = wiki.Ttl_parse(page_ttl_w_ns);
|
||||
Xows_db_row row = new Xows_db_row(wiki.Domain_bry(), ttl, page_id, page_len);
|
||||
cmd.Add_rslt(row);
|
||||
if (++rslts_found == rslts_wanted) break; // stop: found enough results; DATE:2015-04-24
|
||||
}
|
||||
} finally {rdr.Rls();}
|
||||
if (rslts_found == 0) word.Rslts_done_y_(); // read through entire rdr and nothing found; mark word done
|
||||
return rslts_found;
|
||||
}
|
||||
private static final String Search_sql = String_.Concat_lines_nl_skip_last
|
||||
( "SELECT cp.page_id"
|
||||
, ", cp.page_namespace"
|
||||
, ", cp.page_title"
|
||||
, ", cp.page_len"
|
||||
, "FROM {0} sp"
|
||||
, " JOIN <attach_db>page cp ON cp.page_id = sp.{1} "
|
||||
, "WHERE sp.{2} = {3}"
|
||||
, "ORDER BY {4} {5}"
|
||||
, "LIMIT {6}"
|
||||
, "OFFSET {7};"
|
||||
);
|
||||
}
|
||||
36
400_xowa/src/gplx/xowa/specials/search/Xows_db_word.java
Normal file
36
400_xowa/src/gplx/xowa/specials/search/Xows_db_word.java
Normal file
@@ -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.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
public class Xows_db_word {
|
||||
public Xows_db_word(int id, byte[] text, int page_count) {this.id = id; this.text = text; this.page_count = page_count;}
|
||||
public int Id() {return id;} private final int id;
|
||||
public byte[] Text() {return text;} private final byte[] text;
|
||||
public int Page_count() {return page_count;} private final int page_count;
|
||||
public int Rslts_offset() {return rslts_offset;} private int rslts_offset;
|
||||
public boolean Rslts_done() {return rslts_done;} private boolean rslts_done;
|
||||
public void Rslts_offset_add_1() {++rslts_offset;}
|
||||
public void Rslts_done_y_() {rslts_done = true;}
|
||||
}
|
||||
class Xows_db_word_sorter implements gplx.lists.ComparerAble {
|
||||
public int compare(Object lhsObj, Object rhsObj) {
|
||||
Xows_db_word lhs = (Xows_db_word)lhsObj;
|
||||
Xows_db_word rhs = (Xows_db_word)rhsObj;
|
||||
return -Int_.Compare(lhs.Page_count(), rhs.Page_count());
|
||||
}
|
||||
public static final Xows_db_word_sorter Page_count_dsc = new Xows_db_word_sorter(); Xows_db_word_sorter() {}
|
||||
}
|
||||
123
400_xowa/src/gplx/xowa/specials/search/Xows_html_wkr.java
Normal file
123
400_xowa/src/gplx/xowa/specials/search/Xows_html_wkr.java
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.html.*; import gplx.xowa.html.wtrs.*; import gplx.xowa.langs.numbers.*;
|
||||
class Xows_html_wkr {
|
||||
private final Bry_bfr tmp_bfr = Bry_bfr.new_(255);
|
||||
private Xows_ui_qry qry; private Xow_wiki wiki; private Xol_num_mgr num_mgr;
|
||||
private Xoh_lnki_bldr lnki_bldr; private Xoh_anchor_kv_bldr self_lnkr = new Xoh_anchor_kv_bldr(); private Xows_html_row html_rows;
|
||||
public void Init_by_wiki(Xow_wiki wiki, Xol_num_mgr num_mgr, Xows_ui_qry qry) {
|
||||
this.wiki = wiki; this.num_mgr = num_mgr; this.qry = qry;
|
||||
this.lnki_bldr = wiki.App().Html__lnki_bldr();
|
||||
this.html_rows = new Xows_html_row(lnki_bldr);
|
||||
self_lnkr.Init_w_qarg(qry.Special_link_base_href());
|
||||
}
|
||||
public byte[] Gen_page(byte[] tbls) {
|
||||
byte[] rslts_hdr = fmtr_rslts.Bld_bry_many(tmp_bfr, num_mgr.Format_num(qry.Itms_bgn() + List_adp_.Base1), num_mgr.Format_num(qry.Itms_end()), qry.Search_raw());
|
||||
byte[] option_link = lnki_bldr.Href_(Bry_.new_a7("home"), wiki.Ttl_parse(Bry_.new_a7("Help:Options/Search"))).Img_16x16(Xoh_img_path.Img_option).Bld_to_bry();
|
||||
fmtr_page.Bld_bfr_many(tmp_bfr, rslts_hdr, option_link, Paging_link(Bool_.N), Paging_link(Bool_.Y), tbls);
|
||||
return tmp_bfr.Xto_bry_and_clear();
|
||||
}
|
||||
public void Gen_tbl(Bry_bfr bfr, Xows_ui_rslt rslt, byte[] cmd_key, byte[] wiki_domain, boolean searching_db) {
|
||||
html_rows.Init(rslt);
|
||||
byte[] search_link = lnki_bldr.Href_(wiki_domain, wiki.Ttl_parse(self_lnkr.Bld_to_bry())).Caption_(wiki_domain).Img_16x16(Xoh_img_path.Img_search).Img_pos_is_left_(Bool_.Y).Bld_to_bry();
|
||||
fmtr_tbl.Bld_bfr_many(bfr, search_link, searching_db ? Cancel_link(wiki_domain, cmd_key) : Bry_.Empty, Bry_hdr_len, Bry_hdr_ttl, Xows_ui_async.Gen_insert_key(wiki_domain), html_rows);
|
||||
}
|
||||
private byte[] Cancel_link(byte[] domain, byte[] cmd_key) {
|
||||
lnki_bldr.Id_(Bry_.Add(Bry_.new_a7("xowa_cancel_"), domain));
|
||||
lnki_bldr.Href_(wiki, self_lnkr.Add_int(Xows_arg_mgr.Arg_bry_page_index, qry.Page_idx()).Add_bry(Xows_arg_mgr.Arg_bry_cancel, cmd_key).Bld_to_bry());
|
||||
lnki_bldr.Title_(Bry_cancel);
|
||||
lnki_bldr.Img_16x16(Xoh_img_path.Img_cancel);
|
||||
return lnki_bldr.Bld_to_bry();
|
||||
}
|
||||
public byte[] Paging_link(boolean fwd) {
|
||||
int paging_idx = qry.Page_idx();
|
||||
byte[] title = null, img_path = Bry_.Empty;
|
||||
boolean img_pos_is_left = true;
|
||||
if (fwd) {
|
||||
++paging_idx;
|
||||
// if (paging_idx > qry.Page_max()) return Html_entity_.Nbsp_num_bry;
|
||||
img_pos_is_left = false;
|
||||
img_path = Xoh_img_path.Img_go_fwd;
|
||||
title = Bry_paging_fwd;
|
||||
}
|
||||
else {
|
||||
--paging_idx;
|
||||
if (paging_idx < 0) return Html_entity_.Nbsp_num_bry;
|
||||
img_path = Xoh_img_path.Img_go_bwd;
|
||||
title = Bry_paging_bwd;
|
||||
}
|
||||
return lnki_bldr.Title_(title).Href_(wiki, self_lnkr.Add_int(Xows_arg_mgr.Arg_bry_page_index, paging_idx).Bld_to_bry()).Img_16x16(img_path).Img_pos_is_left_(img_pos_is_left).Caption_(title).Bld_to_bry();
|
||||
}
|
||||
private static final Bry_fmtr fmtr_page = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( "~{rslts_hdr}<span style='margin-left:10px'>~{option_link}</span>"
|
||||
, "<div id='xowa_panel_top' style='width:60%;'><div style='float:right;'><span>~{bwd_a}</span><span style='margin-left:10px'>~{fwd_a}</span></div></div>~{tbls}"
|
||||
, "<div id='xowa_panel_bot' style='width:60%;'><div style='float:right;'><span>~{bwd_a}</span><span style='margin-left:10px'>~{fwd_a}</span></div></div>"
|
||||
), "rslts_hdr", "option_link", "bwd_a", "fwd_a", "tbls");
|
||||
private static final Bry_fmtr fmtr_tbl = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( "<table class='wikitable sortable' style='width:60%;'>"
|
||||
, " <tr>"
|
||||
, " <th colspan='2' style='text-align:left'>~{wiki}<span style='float:right'>~{cancel}</span>"
|
||||
, " </th>"
|
||||
, " </tr>"
|
||||
, " <tr>"
|
||||
, " <th width='100'>~{hdr_len}"
|
||||
, " </th>"
|
||||
, " <th>~{hdr_ttl}"
|
||||
, " </th>"
|
||||
, " </tr>~{rows}"
|
||||
, " <tr id='~{insert_key}' style='display:none;'>"
|
||||
, " </tr>"
|
||||
, "</table>"
|
||||
), "wiki", "cancel", "hdr_len", "hdr_ttl", "insert_key", "rows");
|
||||
private static final Bry_fmtr fmtr_rslts = Bry_fmtr.new_("Results <b>~{bgn}</b> of <b>~{end}</b> for <b>~{raw}</b>", "bgn", "end", "raw");
|
||||
private static final byte[] Bry_paging_fwd = Bry_.new_a7("Next"), Bry_paging_bwd = Bry_.new_a7("Previous"), Bry_cancel = Bry_.new_a7("Stop searching")
|
||||
, Bry_hdr_len = Bry_.new_a7("Page length"), Bry_hdr_ttl = Bry_.new_a7("Page title")
|
||||
;
|
||||
}
|
||||
class Xows_html_row implements Bry_fmtr_arg {
|
||||
private final Xoh_lnki_bldr lnki_bldr; private Xows_ui_rslt rslt;
|
||||
private final Object thread_lock = new Object();
|
||||
public Xows_html_row(Xoh_lnki_bldr lnki_bldr) {this.lnki_bldr = lnki_bldr;}
|
||||
public Xows_html_row Init(Xows_ui_rslt rslt) {this.rslt = rslt; return this;}
|
||||
public void XferAry(Bry_bfr bfr, int idx) { // <a href="/wiki/A" title="A" class="xowa-visited">A</a>
|
||||
int len = rslt.Len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Xows_db_row row = rslt.Get_at(i);
|
||||
Gen_html(bfr, row);
|
||||
}
|
||||
}
|
||||
public void Gen_html(Bry_bfr bfr, Xows_db_row row) {
|
||||
synchronized (thread_lock) {
|
||||
lnki_bldr.Href_(row.Wiki_domain(), row.Page_ttl());
|
||||
byte[] title = row.Page_ttl().Full_txt();
|
||||
lnki_bldr.Title_(title);
|
||||
lnki_bldr.Caption_(title);
|
||||
fmtr.Bld_bfr_many(bfr, Html_utl.Encode_id_as_str(row.Key()), row.Page_len(), lnki_bldr.Bld_to_bry());
|
||||
}
|
||||
}
|
||||
public Bry_fmtr Fmtr() {return fmtr;} private final Bry_fmtr fmtr = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( ""
|
||||
, " <tr id='~{page_key}'>"
|
||||
, " <td style='padding-right:5px; vertical-align:top; text-align:right;'>~{page_len}"
|
||||
, " </td>"
|
||||
, " <td style='padding-left:5px; vertical-align:top;'>~{lnki}" // SERVER:"<a href='"; DATE:2015-04-16
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
), "page_key", "page_len", "lnki");
|
||||
}
|
||||
@@ -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.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import org.junit.*; import gplx.xowa.html.wtrs.*; import gplx.xowa.tdbs.*; import gplx.xowa.wikis.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
public class Xows_html_wkr_tst {
|
||||
@Before public void init() {fxt.Clear();} private Xows_html_wkr_fxt fxt = new Xows_html_wkr_fxt();
|
||||
@Test public void Paging() {
|
||||
fxt.Test_paging(Bool_.Y, 1, "<a href='/site/en.wikipedia.org/wiki/Special:Search/A%3Ffulltext%3Dy%26xowa_page_index%3D2' title='Next'>Next<img src='file:///mem/xowa/user/anonymous/app/img/window/paging/go_fwd.png' width='16' height='16'/></a>");
|
||||
fxt.Test_paging(Bool_.N, 1, "<a href='/site/en.wikipedia.org/wiki/Special:Search/A%3Ffulltext%3Dy%26xowa_page_index%3D0' title='Previous'><img src='file:///mem/xowa/user/anonymous/app/img/window/paging/go_bwd.png' width='16' height='16'/>Previous</a>");
|
||||
fxt.Test_paging(Bool_.Y, 2, "<a href='/site/en.wikipedia.org/wiki/Special:Search/A%3Ffulltext%3Dy%26xowa_page_index%3D3' title='Next'>Next<img src='file:///mem/xowa/user/anonymous/app/img/window/paging/go_fwd.png' width='16' height='16'/></a>");
|
||||
fxt.Test_paging(Bool_.N, 0, " ");
|
||||
}
|
||||
@Test public void Rows() {
|
||||
fxt.Test_rows(Xows_db_row.Ary(fxt.Make_row(10, "A"), fxt.Make_row(20, "B")), String_.Concat_lines_nl_skip_last
|
||||
( ""
|
||||
, " <tr id='w.7CA'>"
|
||||
, " <td style='padding-right:5px; vertical-align:top; text-align:right;'>10"
|
||||
, " </td>"
|
||||
, " <td style='padding-left:5px; vertical-align:top;'><a href='/site/w/wiki/A' title='A'>A</a>"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
, " <tr id='w.7CB'>"
|
||||
, " <td style='padding-right:5px; vertical-align:top; text-align:right;'>20"
|
||||
, " </td>"
|
||||
, " <td style='padding-left:5px; vertical-align:top;'><a href='/site/w/wiki/B' title='B'>B</a>"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
));
|
||||
}
|
||||
}
|
||||
class Xows_html_wkr_fxt {
|
||||
private Xoae_app app; private Xowe_wiki wiki; private Xows_html_wkr html_mgr; private final Bry_bfr tmp_bfr = Bry_bfr.new_(255);
|
||||
public Xows_html_wkr_fxt Clear() {
|
||||
if (app == null) {
|
||||
app = Xoa_app_fxt.app_();
|
||||
wiki = Xoa_app_fxt.wiki_tst_(app);
|
||||
html_mgr = new Xows_html_wkr();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public void Test_paging(boolean fwd, int paging_idx, String expd) {
|
||||
Xows_ui_qry qry = new Xows_ui_qry(Bry_.new_a7("A"), paging_idx, 100, Xosrh_rslt_itm_sorter.Tid_len_dsc, new Xows_ns_mgr(), true, new Xow_domain[] {Xow_domain_.parse(wiki.Domain_bry())});
|
||||
qry.Page_max_(2);
|
||||
html_mgr.Init_by_wiki(wiki, wiki.Lang().Num_mgr(), qry);
|
||||
byte[] paging_link = html_mgr.Paging_link(fwd);
|
||||
Tfds.Eq(expd, String_.new_a7(paging_link));
|
||||
}
|
||||
public void Test_rows(Xows_db_row[] rows, String expd) {
|
||||
Xows_ui_rslt rslt = new Xows_ui_rslt();
|
||||
Xows_html_row html_row = new Xows_html_row(wiki.App().Html__lnki_bldr());
|
||||
html_row.Init(rslt);
|
||||
for (int i = 0; i < rows.length; ++i)
|
||||
rslt.Add(rows[i]);
|
||||
html_row.XferAry(tmp_bfr, 0);
|
||||
Tfds.Eq_str_lines(expd, tmp_bfr.Xto_str_and_clear());
|
||||
}
|
||||
public Xows_db_row Make_row(int len, String ttl_str) {
|
||||
byte[] ttl_bry = Bry_.new_u8(ttl_str);
|
||||
return new Xows_db_row(Bry_.new_a7("w"), wiki.Ttl_parse(ttl_bry), 1, len);
|
||||
}
|
||||
}
|
||||
81
400_xowa/src/gplx/xowa/specials/search/Xows_ns_mgr.java
Normal file
81
400_xowa/src/gplx/xowa/specials/search/Xows_ns_mgr.java
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.core.primitives.*;
|
||||
public class Xows_ns_mgr {
|
||||
private final Ordered_hash ns_hash = Ordered_hash_.new_(); private final Int_obj_ref tmp_ns_id = Int_obj_ref.neg1_(); private final Bry_bfr tmp_bfr = Bry_bfr.reset_(32);
|
||||
private boolean ns_all, ns_main;
|
||||
public void Clear() {
|
||||
ns_hash.Clear();
|
||||
ns_all = ns_main = false;
|
||||
}
|
||||
public boolean Has(int ns_id) {
|
||||
return ns_all // all flag set
|
||||
|| ns_main && ns_id == Xow_ns_.Id_main // main flag set
|
||||
|| ns_hash.Has(tmp_ns_id.Val_(ns_id)) // check against ns_hash
|
||||
;
|
||||
}
|
||||
public void Add_by_id(int ns_id) {
|
||||
if (ns_hash.Has(tmp_ns_id.Val_(ns_id)))
|
||||
ns_hash.Del(tmp_ns_id);
|
||||
ns_hash.Add_as_key_and_val(Int_obj_ref.new_(ns_id));
|
||||
}
|
||||
public void Add_by_name(byte[] ns_name) {
|
||||
int id = Xow_ns_.Canonical_id(ns_name);
|
||||
if (id != Xow_ns_.Id_null)
|
||||
Add_by_id(id);
|
||||
}
|
||||
public void Add_all() {
|
||||
ns_all = true;
|
||||
}
|
||||
public void Add_by_parse(byte[] key, byte[] val) {
|
||||
int ns_enabled = Bry_.Xto_int(val);
|
||||
if (ns_enabled == 1) { // make sure set to 1; EX: ignore &ns0=0
|
||||
int key_len = key.length;
|
||||
if (key_len == 3 && key[2] == Byte_ascii.Star) // translate ns* as ns_all
|
||||
ns_all = true;
|
||||
else {
|
||||
int ns_id = Bry_.Xto_int_or(key, 2, key_len, Int_.MinValue);
|
||||
if (ns_id != Int_.MinValue) { // ignore invalid ints; EX: &nsabc=1;
|
||||
Add_by_id(ns_id);
|
||||
ns_main = ns_all = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public void Add_main_if_empty() {
|
||||
if (ns_hash.Count() == 0)
|
||||
ns_main = true;
|
||||
}
|
||||
public byte[] To_hash_key() {
|
||||
if (ns_all)
|
||||
return Hash_key_all;
|
||||
else if (ns_main)
|
||||
return Hash_key_main;
|
||||
else {
|
||||
int ns_hash_len = ns_hash.Count();
|
||||
for (int i = 0; i < ns_hash_len; i++) {
|
||||
if (i != 0) tmp_bfr.Add_byte_semic();
|
||||
Int_obj_ref ns_id_ref = (Int_obj_ref)ns_hash.Get_at(i);
|
||||
tmp_bfr.Add_int_variable(ns_id_ref.Val());
|
||||
}
|
||||
return tmp_bfr.Xto_bry_and_clear();
|
||||
}
|
||||
}
|
||||
private static final byte[] Hash_key_all = new byte[] {Byte_ascii.Star}, Hash_key_main = new byte[] {Byte_ascii.Num_0};
|
||||
}
|
||||
102
400_xowa/src/gplx/xowa/specials/search/Xows_page__search.java
Normal file
102
400_xowa/src/gplx/xowa/specials/search/Xows_page__search.java
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.core.primitives.*; import gplx.xowa.wikis.*; import gplx.xowa.apis.xowa.specials.*;
|
||||
import gplx.xowa.wikis.domains.crts.*;
|
||||
public class Xows_page__search implements Xows_page, GfoInvkAble, GfoEvObj {
|
||||
private final Xoae_app app; private final Xow_domain wiki_domain; private final Xoapi_search search_api;
|
||||
private final Xows_core search_mgr; private final Xows_arg_mgr args_mgr = new Xows_arg_mgr();
|
||||
private Xow_domain[] search_domain_ary;
|
||||
public Xows_page__search(Xowe_wiki wiki) {
|
||||
this.app = wiki.Appe();
|
||||
this.wiki_domain = wiki.Domain_itm();
|
||||
this.search_mgr = new Xows_core(wiki.Appe().Wiki_mgr());
|
||||
this.ev_mgr = GfoEvMgr.new_(this);
|
||||
this.search_api = wiki.Appe().Api_root().Special().Search();
|
||||
GfoEvMgr_.SubSame_many(search_api, this, Xoapi_search.Evt_multi_wikis_changed, Xoapi_search.Evt_multi_wikis_changed);
|
||||
}
|
||||
public GfoEvMgr EvMgr() {return ev_mgr;} private GfoEvMgr ev_mgr;
|
||||
public Xows_special_meta Special_meta() {return Xows_special_meta_.Itm__search;}
|
||||
private void Multi_wikis_changed() {
|
||||
Xow_domain_crt_itm crt = search_api.Multi_wikis_crt(wiki_domain);
|
||||
this.search_domain_ary = app.Usere().Wiki().Xwiki_mgr().Get_by_crt(wiki_domain, crt);
|
||||
if (search_domain_ary.length == 0) search_domain_ary = new Xow_domain[] {wiki_domain}; // default to current if bad input
|
||||
Multi_sorts_changed();
|
||||
}
|
||||
private void Multi_sorts_changed() {
|
||||
Xow_domain_crt_itm[] ary = search_api.Multi_sorts_crt(wiki_domain);
|
||||
if (ary == null) return; // default to no sort if bad input
|
||||
Xow_domain_sorter__manual sorter = new Xow_domain_sorter__manual(wiki_domain, ary);
|
||||
Xow_domain_sorter__manual.Sort(sorter, search_domain_ary);
|
||||
}
|
||||
public void Special_gen(Xowe_wiki wiki, Xoae_page page, Xoa_url url, Xoa_ttl ttl) {
|
||||
if (wiki.Domain_tid() == Xow_domain_type_.Tid_home) return; // do not allow search in home wiki; will throw null ref error b/c no search_ttl dirs
|
||||
if (search_domain_ary == null) Multi_wikis_changed();
|
||||
// get args
|
||||
Xog_search_suggest_mgr search_suggest_mgr = wiki.Appe().Gui_mgr().Search_suggest_mgr();
|
||||
args_mgr.Clear();
|
||||
args_mgr.Parse(search_suggest_mgr.Args_default());
|
||||
args_mgr.Parse(url.Args());
|
||||
args_mgr.Ns_mgr().Add_main_if_empty();
|
||||
// get search_bry
|
||||
byte[] search_bry = args_mgr.Search_bry();
|
||||
if (search_bry == null) { // search is not in qarg; EX:Special:Search?search=Earth
|
||||
search_bry = ttl.Leaf_txt_wo_qarg(); // assume search is in leaf; EX: Special:Search/Earth
|
||||
args_mgr.Search_bry_(search_bry);
|
||||
}
|
||||
if ( search_suggest_mgr.Auto_wildcard() // add * automatically if option set
|
||||
&& wiki.Db_mgr().Tid() == gplx.xowa.dbs.Xodb_mgr_sql.Tid_sql // only apply to sql
|
||||
&& Bry_finder.Find_fwd(search_bry, Byte_ascii.Star) == -1 // search term does not have asterisk
|
||||
)
|
||||
search_bry = Bry_.Add(search_bry, Byte_ascii.Star);
|
||||
url.Page_bry_(Bry_.Add(Xows_special_meta_.Itm__search.Ttl_bry(), Byte_ascii.Slash_bry, search_bry));// HACK: need to re-set Page b/c href_parser does not eliminate qargs; DATE:2013-02-08
|
||||
// search wiki
|
||||
Xoa_ttl search_ttl = Xoa_ttl.parse_(wiki, search_bry);
|
||||
Xoae_page search_page = page;
|
||||
if (!Bry_.Eq(search_bry, Xows_special_meta_.Itm__search.Ttl_bry())) // do not lookup page else stack overflow; happens when going directly to Special:Search (from history)
|
||||
search_page = wiki.Data_mgr().Get_page(search_ttl, false); // try to find page; EX:Special:Search?search=Earth -> en.w:Earth; needed for search suggest
|
||||
// page not found, or explicit_search invoked
|
||||
if (search_page.Missing() || url.Search_fulltext()) {
|
||||
if (args_mgr.Cancel() != null) {
|
||||
search_mgr.Cancel(args_mgr.Cancel());
|
||||
page.Tab_data().Cancel_show_y_();
|
||||
return;
|
||||
}
|
||||
page.Html_data().Html_restricted_n_();
|
||||
page.Html_data().Xtn_search_text_(search_bry);
|
||||
Xows_ui_qry qry = new Xows_ui_qry(search_bry, args_mgr.Paging_idx(), search_api.Results_per_page(), args_mgr.Sort_tid(), args_mgr.Ns_mgr(), search_api.Async_db(), search_domain_ary);
|
||||
search_mgr.Search(wiki, page, qry);
|
||||
}
|
||||
// page found; return it;
|
||||
else {
|
||||
wiki.ParsePage(search_page, true);
|
||||
page.Data_raw_(search_page.Data_raw());
|
||||
if (page.Root() != null) // NOTE: null when going from w:Earth -> q:Earth; DATE:2013-03-20
|
||||
page.Root().Data_htm_(search_page.Root().Data_htm());
|
||||
page.Ttl_(search_ttl).Url_(Xoa_url.new_(wiki.Domain_bry(), search_ttl.Full_txt())).Redirected_(true);
|
||||
}
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Xoapi_search.Evt_multi_wikis_changed)) Multi_wikis_changed();
|
||||
else if (ctx.Match(k, Xoapi_search.Evt_multi_sorts_changed)) Multi_sorts_changed();
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
return this;
|
||||
}
|
||||
public static final byte Match_tid_all = 0, Match_tid_bgn = 1;
|
||||
public static final byte Version_null = 0, Version_1 = 1, Version_2 = 2;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.core.brys.*;
|
||||
class Xows_paging_parser {
|
||||
private final List_adp itm_list = List_adp_.new_();
|
||||
private final Bry_rdr rdr = new Bry_rdr();
|
||||
public Xows_paging_itm[] Parse(byte[] raw) { // EX: en.wikipedia.org|41|60;en.wiktionary.org|21|40;
|
||||
rdr.Init(raw);
|
||||
while (!rdr.Pos_is_eos()) {
|
||||
byte[] wiki = rdr.Read_bry_to_pipe();
|
||||
int bgn = rdr.Read_int_to_pipe();
|
||||
int end = rdr.Read_int_to_semic();
|
||||
Xows_paging_itm itm = new Xows_paging_itm(wiki, bgn, end);
|
||||
itm_list.Add(itm);
|
||||
}
|
||||
return (Xows_paging_itm[])itm_list.To_ary_and_clear(Xows_paging_itm.class);
|
||||
}
|
||||
}
|
||||
class Xows_paging_itm {
|
||||
public Xows_paging_itm(byte[] wiki, int bgn, int end) {this.wiki = wiki; this.bgn = bgn; this.end = end;}
|
||||
public byte[] Wiki() {return wiki;} private final byte[] wiki;
|
||||
public int Bgn() {return bgn;} private final int bgn;
|
||||
public int End() {return end;} private final int end;
|
||||
}
|
||||
70
400_xowa/src/gplx/xowa/specials/search/Xows_ui_async.java
Normal file
70
400_xowa/src/gplx/xowa/specials/search/Xows_ui_async.java
Normal file
@@ -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.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.html.*; import gplx.xowa.files.gui.*;
|
||||
class Xows_ui_async {
|
||||
private final Xows_html_row html_row; private final Xog_js_wkr js_wkr;
|
||||
private final Xows_db_row[] rows; private final int rows_len;
|
||||
private final Bry_bfr bfr = Bry_bfr.new_(255);
|
||||
private final byte[] insert_new_key;
|
||||
private final Cancelable cxl;
|
||||
public Xows_ui_async(Cancelable cxl, Xows_html_row html_row, Xog_js_wkr js_wkr, int paging_len, byte[] wiki) {
|
||||
this.cxl = cxl;
|
||||
this.html_row = html_row; this.js_wkr = js_wkr;
|
||||
this.rows = new Xows_db_row[paging_len];
|
||||
this.rows_len = paging_len;
|
||||
this.insert_new_key = Gen_insert_key(wiki);
|
||||
}
|
||||
public void Add(Xows_db_row new_row) {
|
||||
Xows_db_row last_row = rows[rows_len - 1];
|
||||
if (last_row != null) {
|
||||
if (Compare(new_row, last_row) == CompareAble_.MoreOrSame) return; // new_row is < last_row; exit
|
||||
}
|
||||
int new_row_slot = Find_insert_slot(new_row); if (new_row_slot == -1) return;
|
||||
Xows_db_row insert_row = rows[new_row_slot];
|
||||
byte[] insert_key = insert_row == null ? insert_new_key : insert_row.Key();
|
||||
Displace(new_row_slot, new_row);
|
||||
html_row.Gen_html(bfr, new_row);
|
||||
String html_tbl = bfr.Xto_str_and_clear();
|
||||
if (cxl.Canceled()) return;
|
||||
js_wkr.Html_elem_append_above(Html_utl.Encode_id_as_str(insert_key), html_tbl);
|
||||
if (last_row != null) {
|
||||
if (cxl.Canceled()) return;
|
||||
js_wkr.Html_elem_replace_html(Html_utl.Encode_id_as_str(last_row.Key()), "");
|
||||
}
|
||||
}
|
||||
private int Find_insert_slot(Xows_db_row new_row) {
|
||||
for (int i = 0; i < rows_len; ++i) {
|
||||
Xows_db_row cur_row = rows[i];
|
||||
if (cur_row == null) return i;
|
||||
if (Compare(new_row, cur_row) == CompareAble_.Less) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
private void Displace(int new_row_slot, Xows_db_row new_row) {
|
||||
for (int i = rows_len - 2; i >= new_row_slot; --i) {
|
||||
rows[i + 1] = rows[i];
|
||||
}
|
||||
rows[new_row_slot] = new_row;
|
||||
}
|
||||
private int Compare(Xows_db_row lhs, Xows_db_row rhs) {
|
||||
return -Int_.Compare(lhs.Page_len(), rhs.Page_len());
|
||||
}
|
||||
public static byte[] Gen_insert_key(byte[] wiki) {return Bry_.Add(Bry_insert_key, wiki);}
|
||||
private static final byte[] Bry_insert_key = Bry_.new_a7("xowa_insert_");
|
||||
}
|
||||
@@ -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.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import org.junit.*; import gplx.xowa.html.wtrs.*; import gplx.xowa.files.gui.*;
|
||||
public class Xows_ui_async_tst {
|
||||
@Before public void init() {fxt.Clear();} private Xows_ui_async_fxt fxt = new Xows_ui_async_fxt();
|
||||
@Test public void Basic() {
|
||||
fxt.Test_add(fxt.Make_rslt(50, "L"), fxt.Make_args_append("xowa_insert_w" , "w.7CL")); // insert new
|
||||
fxt.Test_add(fxt.Make_rslt(30, "N"), fxt.Make_args_append("xowa_insert_w" , "w.7CN")); // insert below last
|
||||
fxt.Test_add(fxt.Make_rslt(70, "J"), fxt.Make_args_append("w.7CL" , "w.7CJ")); // insert above first
|
||||
fxt.Test_add(fxt.Make_rslt(60, "K"), fxt.Make_args_append("w.7CL" , "w.7CK")); // insert above mid
|
||||
fxt.Test_add(fxt.Make_rslt(40, "M"), fxt.Make_args_append("w.7CN" , "w.7CM")); // insert below mid
|
||||
fxt.Test_add(fxt.Make_rslt(10, "P")); // insert noop
|
||||
fxt.Test_add(fxt.Make_rslt(80, "I"), fxt.Make_args_append("w.7CJ" , "w.7CI") , fxt.Make_args_replace("w.7CN")); // insert displace all
|
||||
fxt.Test_add(fxt.Make_rslt(61, "K1"), fxt.Make_args_append("w.7CK" , "w.7CK1"), fxt.Make_args_replace("w.7CM")); // insert displace mid
|
||||
}
|
||||
}
|
||||
class Xows_ui_async_fxt {
|
||||
private Xows_html_row html_row; private static final byte[] Bry_enwiki = Bry_.new_a7("w");
|
||||
private Xows_ui_async async;
|
||||
private Xog_js_wkr__log js_wkr = new Xog_js_wkr__log();
|
||||
private Xowe_wiki wiki;
|
||||
public void Clear() {
|
||||
Xoae_app app = Xoa_app_fxt.app_();
|
||||
this.wiki = Xoa_app_fxt.wiki_(app, "w");
|
||||
html_row = new Xows_html_row(wiki.App().Html__lnki_bldr());
|
||||
html_row.Fmtr().Fmt_("~{page_key}");
|
||||
async = new Xows_ui_async(Cancelable_.Never, html_row, js_wkr, 5, Bry_enwiki);
|
||||
}
|
||||
public Xows_db_row Make_rslt(int len, String ttl) {
|
||||
byte[] ttl_bry = Bry_.new_a7(ttl);
|
||||
return new Xows_db_row(Bry_enwiki, wiki.Ttl_parse(ttl_bry), 1, len);
|
||||
}
|
||||
public Object[] Make_args_append(String uid, String html) {return Object_.Ary(Xog_js_wkr__log.Proc_append_above, uid, html);}
|
||||
public Object[] Make_args_replace(String uid) {return Object_.Ary(Xog_js_wkr__log.Proc_replace_html, uid, "");}
|
||||
public void Test_add(Xows_db_row row, Object[]... expd) {
|
||||
async.Add(row);
|
||||
int expd_len = expd.length;
|
||||
Tfds.Eq(expd_len, js_wkr.Log__len());
|
||||
for (int i = 0; i < expd_len; ++i) {
|
||||
String expd_str = String_.ConcatWith_any("\n", expd[i]);
|
||||
String actl_str = String_.ConcatWith_any("\n", js_wkr.Log__get_at(i));
|
||||
Tfds.Eq_str_lines(expd_str, actl_str);
|
||||
}
|
||||
js_wkr.Log__clear();
|
||||
}
|
||||
}
|
||||
116
400_xowa/src/gplx/xowa/specials/search/Xows_ui_cmd.java
Normal file
116
400_xowa/src/gplx/xowa/specials/search/Xows_ui_cmd.java
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.core.threads.*; import gplx.html.*;
|
||||
import gplx.xowa.wikis.*; import gplx.xowa.files.gui.*; import gplx.xowa.gui.views.*;
|
||||
class Xows_ui_cmd implements GfoInvkAble, Cancelable, Xog_tab_close_lnr {
|
||||
private final Xows_core mgr; private final Xows_ui_qry qry; private final Xows_ui_rslt rslt;
|
||||
private final Xow_wiki wiki; private final Xoae_page page; private final Xog_tab_close_mgr tab_close_mgr; private final Xog_js_wkr js_wkr;
|
||||
private final boolean async; private Xows_ui_async async_wkr;
|
||||
private Xows_db_cache cache;
|
||||
public Xows_ui_cmd(Xows_core mgr, Xows_ui_qry qry, Xow_wiki wiki, Xoae_page page, Xog_tab_close_mgr tab_close_mgr, Xog_js_wkr js_wkr) {
|
||||
this.mgr = mgr; this.qry = qry; this.wiki = wiki; this.page = page; this.tab_close_mgr = tab_close_mgr; this.js_wkr = js_wkr;
|
||||
this.async = wiki.App().App_type().Uid_is_gui() && qry.Async_db();
|
||||
this.rslt = new Xows_ui_rslt();
|
||||
this.key = Html_utl.Encode_id_as_bry(Bry_.Add(qry.Key(), Byte_ascii.Pipe_bry, wiki.Domain_bry()));
|
||||
}
|
||||
public byte[] Key() {return key;} private final byte[] key;
|
||||
public Xow_wiki Wiki() {return wiki;}
|
||||
public Xows_ui_rslt Rslt() {return rslt;}
|
||||
public boolean Canceled() {return canceled;} private boolean canceled;
|
||||
public void Cancel() {
|
||||
Xoa_app_.Usr_dlg().Prog_many("", "", "search canceled: key=~{0}", key);
|
||||
canceled = true;
|
||||
this.Hide_cancel_btn();
|
||||
}
|
||||
public void Cancel_reset() {}
|
||||
public boolean Search() {
|
||||
this.cache = mgr.Get_cache_or_new(key);
|
||||
boolean rv = false, fill_from_cache = true;
|
||||
if (!cache.Done() && (qry.Itms_end() > cache.Itms_end())) {
|
||||
if (async) {
|
||||
fill_from_cache = false; // NOTE: do not retrieve cached results to page, else ui_async cmd will add out of order; DATE:2015-04-24
|
||||
if (async_wkr == null) async_wkr = new Xows_ui_async(this, new Xows_html_row(new gplx.xowa.html.wtrs.Xoh_lnki_bldr(wiki.App(), wiki.App().Html__href_parser())), js_wkr, qry.Page_len(), wiki.Domain_bry());
|
||||
Thread_adp_.invk_(gplx.xowa.apps.Xoa_thread_.Key_special_search_db, this, Invk_search_db).Start();
|
||||
}
|
||||
else
|
||||
Search_db();
|
||||
rv = true;
|
||||
}
|
||||
if (fill_from_cache) {
|
||||
cache.Get_between(rslt, qry.Itms_bgn(), qry.Itms_end());
|
||||
qry.Page_max_(cache.Count() / qry.Page_len());
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public void Search_db() {
|
||||
tab_close_mgr.Add(this);
|
||||
if (async) {
|
||||
while (!page.Html_data().Mode_wtxt_shown()) // NOTE:must check for wtxt_shown else async can happen first, and then be overwritten by wtxt; DATE:2015-04-26
|
||||
Thread_adp_.Sleep(100);
|
||||
// show any existing items in the cache on screen; new updates wil bump these off; SEE:NOTE:show_existing;DATE:2015-04-26
|
||||
int qry_itms_bgn = qry.Itms_bgn(), cache_count = cache.Count();
|
||||
for (int i = qry_itms_bgn; i < cache_count; ++i)
|
||||
async_wkr.Add(cache.Get_at(i));
|
||||
}
|
||||
new Xows_db_wkr().Search(this, qry, rslt, cache, wiki);
|
||||
mgr.Search_end(this);
|
||||
if (this.Canceled()) return; // NOTE: must check else throws SWT exception
|
||||
this.Hide_cancel_btn();
|
||||
if (cache.Done())
|
||||
qry.Page_max_(cache.Count() / qry.Page_len());
|
||||
Xoa_app_.Usr_dlg().Prog_many("", "", "");
|
||||
}
|
||||
private void Hide_cancel_btn() {
|
||||
Thread_adp_.invk_(gplx.xowa.apps.Xoa_thread_.Key_special_search_cancel, this, Invk_hide_cancel).Start();
|
||||
}
|
||||
private void Hide_cancel_btn_async() {
|
||||
js_wkr.Html_atr_set("xowa_cancel_" + wiki.Domain_str(), "style", "display:none;");
|
||||
}
|
||||
public void Add_rslt(Xows_db_row rslt) {
|
||||
cache.Add(rslt);
|
||||
if (async) async_wkr.Add(rslt);
|
||||
}
|
||||
public boolean When_close(Xog_tab_itm tab, Xoa_url url) {
|
||||
if (url != Xoa_url.Null) { // not called by close_tab (Ctrl+W)
|
||||
byte[] cancel_arg = url.Args_hash().Get_val_bry_or(Xows_arg_mgr.Arg_bry_cancel, null);
|
||||
if (cancel_arg != null) return true; // cancel arg exists; assume tab is not being closed; note that cancel will be processed by Xows_page__special; DATE:2015-04-30
|
||||
}
|
||||
this.Cancel();
|
||||
return true;
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_search_db)) Search_db();
|
||||
else if (ctx.Match(k, Invk_hide_cancel)) Hide_cancel_btn_async();
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
return this;
|
||||
}
|
||||
private static final String Invk_search_db = "search_db", Invk_hide_cancel = "hide_cancel";
|
||||
}
|
||||
/*
|
||||
NOTE:show_existing. code needed to show A1
|
||||
EX: search="A*": "A" has 400 words; "A1" has 1;
|
||||
. search 1-20 returns 20 words for A and 1 word for A1.
|
||||
.. the 1st A word has a len of 999 and the 20th A word has a length of 900;
|
||||
.. A1 has a length of 799
|
||||
. search 21-40 returns 20 words for A
|
||||
.. the 21st word has a len of 899 and the 40th has a len of 800
|
||||
.. A1 should show up briefly, and then get pushed off screen by 21-40
|
||||
. search 61-40 returns 20 words for A
|
||||
.. A1 must show up
|
||||
*/
|
||||
45
400_xowa/src/gplx/xowa/specials/search/Xows_ui_qry.java
Normal file
45
400_xowa/src/gplx/xowa/specials/search/Xows_ui_qry.java
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.xowa.wikis.*;
|
||||
class Xows_ui_qry {
|
||||
private final List_adp cmd_list = List_adp_.new_();
|
||||
public Xows_ui_qry(byte[] search_raw, int page_idx, int page_len, byte sort_tid, Xows_ns_mgr ns_mgr, boolean async_db, Xow_domain[] wiki_domains) {
|
||||
this.search_raw = search_raw; this.page_idx = page_idx; this.page_len = page_len; this.sort_tid = sort_tid; this.ns_mgr = ns_mgr; this.async_db = async_db; this.wiki_domains = wiki_domains;
|
||||
this.itms_bgn = page_idx * page_len;
|
||||
this.page_max = page_idx; // default page_max to page_idx; adjust later when all results are known
|
||||
this.key = Bry_.Add_w_dlm(Byte_ascii.Pipe, search_raw, ns_mgr.To_hash_key());
|
||||
this.special_link_base_href = Bry_.Add(Bry_.new_a7("Special:Search/"), search_raw, Bry_.new_a7("?fulltext=y"));
|
||||
}
|
||||
public byte[] Key() {return key;} private final byte[] key;
|
||||
public byte[] Search_raw() {return search_raw;} private final byte[] search_raw;
|
||||
public boolean Async_db() {return async_db;} private boolean async_db;
|
||||
public int Page_idx() {return page_idx;} private final int page_idx;
|
||||
public int Page_max() {return page_max;} private int page_max;
|
||||
public int Page_len() {return page_len;} private final int page_len;
|
||||
public int Itms_bgn() {return itms_bgn;} private final int itms_bgn;
|
||||
public int Itms_end() {return itms_bgn + page_len;}
|
||||
public byte Sort_tid() {return sort_tid;} private final byte sort_tid;
|
||||
public Xows_ns_mgr Ns_mgr() {return ns_mgr;} private final Xows_ns_mgr ns_mgr;
|
||||
public Xow_domain[] Wiki_domains() {return wiki_domains;} private final Xow_domain[] wiki_domains;
|
||||
public void Page_max_(int v) {this.page_max = v;}
|
||||
public int Cmds__len() {return cmd_list.Count();}
|
||||
public Xows_ui_cmd Cmds__get_at(int i) {return (Xows_ui_cmd)cmd_list.Get_at(i);}
|
||||
public void Cmds__add(Xows_ui_cmd cmd) {cmd_list.Add(cmd);}
|
||||
public byte[] Special_link_base_href() {return special_link_base_href;} private final byte[] special_link_base_href;
|
||||
}
|
||||
24
400_xowa/src/gplx/xowa/specials/search/Xows_ui_rslt.java
Normal file
24
400_xowa/src/gplx/xowa/specials/search/Xows_ui_rslt.java
Normal file
@@ -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.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
class Xows_ui_rslt {
|
||||
private final List_adp rslt_list = List_adp_.new_();
|
||||
public int Len() {return rslt_list.Count();}
|
||||
public void Add(Xows_db_row rslt) {rslt_list.Add(rslt);}
|
||||
public Xows_db_row Get_at(int i) {return (Xows_db_row)rslt_list.Get_at(i);}
|
||||
}
|
||||
@@ -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.specials.search.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.search.*;
|
||||
import gplx.core.primitives.*;
|
||||
class Xows_text_parser__v1 {
|
||||
private Xol_lang lang; private Bry_bfr bfr = Bry_bfr.new_(255);
|
||||
private final Ordered_hash list = Ordered_hash_.new_bry_();
|
||||
public void Init(Xol_lang lang) {this.lang = lang;}
|
||||
public void Parse(byte[] src, int src_len, int bgn, int end) {
|
||||
if (lang != null) { // null lang passed in by searcher
|
||||
src = lang.Case_mgr().Case_build_lower(src);
|
||||
src_len = src.length;
|
||||
}
|
||||
int i = 0; boolean word_done = false;
|
||||
while (true) {
|
||||
if (word_done || i == src_len) {
|
||||
if (bfr.Len() > 0) {
|
||||
byte[] word = bfr.Xto_bry_and_clear();
|
||||
if (!list.Has(word)) list.Add(word, word); // don't add same word twice; EX: Title of "Can Can" should only have "Can" in index
|
||||
}
|
||||
if (i == src_len) break;
|
||||
word_done = false;
|
||||
}
|
||||
byte b = src[i];
|
||||
switch (b) {
|
||||
case Byte_ascii.Underline: // underline is word-breaking; EX: A_B -> A, B
|
||||
case Byte_ascii.Space: // should not occur, but just in case (only underscores)
|
||||
case Byte_ascii.Tab: case Byte_ascii.Nl: case Byte_ascii.Cr: // should not occur in titles, but just in case
|
||||
|
||||
case Byte_ascii.Dash: // treat hypenated words separately
|
||||
case Byte_ascii.Dot: // treat abbreviations as separate words; EX: A.B.C.
|
||||
case Byte_ascii.Bang: case Byte_ascii.Hash: case Byte_ascii.Dollar: case Byte_ascii.Percent:
|
||||
case Byte_ascii.Amp: case Byte_ascii.Paren_bgn: case Byte_ascii.Paren_end: case Byte_ascii.Star:
|
||||
case Byte_ascii.Comma: case Byte_ascii.Slash:
|
||||
case Byte_ascii.Colon: case Byte_ascii.Semic: case Byte_ascii.Gt:
|
||||
case Byte_ascii.Question: case Byte_ascii.At: case Byte_ascii.Brack_bgn: case Byte_ascii.Brack_end:
|
||||
case Byte_ascii.Pow: case Byte_ascii.Tick:
|
||||
case Byte_ascii.Curly_bgn: case Byte_ascii.Pipe: case Byte_ascii.Curly_end: case Byte_ascii.Tilde:
|
||||
case Byte_ascii.Quote: case Byte_ascii.Apos: // FUTURE: apos will split "Earth's" to Earth and s; should remove latter
|
||||
++i;
|
||||
word_done = true;
|
||||
break;
|
||||
default:
|
||||
bfr.Add_byte(b);
|
||||
++i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// byte[][] rv = (byte[][])list.To_ary(typeof(byte[]));
|
||||
// list.Clear(); list.Resize_bounds(16);
|
||||
// return rv;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.search.*;
|
||||
import gplx.core.btries.*; import gplx.xowa.langs.cases.*;
|
||||
class Xows_text_parser__v2 {
|
||||
private final Btrie_slim_mgr trie = Btrie_slim_mgr.cs_();
|
||||
private final Bry_bfr bfr = Bry_bfr.new_(32);
|
||||
private Xob_word_mgr word_mgr; private Xol_case_mgr case_mgr;
|
||||
private byte[] src; private int end; // bgn,
|
||||
private boolean dirty; private Xows_text_tkn__split parser__ws;
|
||||
public void Init_for_ttl(Xob_word_mgr word_mgr, Xol_case_mgr case_mgr) {
|
||||
this.word_mgr = word_mgr; this.case_mgr = case_mgr;
|
||||
trie.Clear();
|
||||
this.parser__ws = Xows_text_tkn__split.new_(trie, Bool_.N, " ", "\t", "\n", "\r", "_");
|
||||
Xows_text_tkn__split.new_(trie, Bool_.N, "!", "?");
|
||||
Xows_text_tkn__split.new_(trie, Bool_.N, "(", ")");
|
||||
Xows_text_tkn__split.new_(trie, Bool_.N, "/");
|
||||
Xows_text_tkn__ellipsis.new_(trie, "..");
|
||||
Xows_text_tkn__apos.new_(trie, "'", Byte_ascii.Ltr_s);
|
||||
}
|
||||
public void Parse(byte[] src, int src_len, int bgn, int end) {
|
||||
this.src = src; this.end = end; // this.bgn = bgn;
|
||||
this.dirty = false; this.bgn__ws = bgn__dash = bgn__slash = -1;
|
||||
this.src = case_mgr.Case_build_lower(src); src_len = this.src.length;
|
||||
int pos = bgn;
|
||||
while (true) {
|
||||
boolean is_last = pos == end;
|
||||
if (is_last) { // do split
|
||||
Word__add(bgn__ws, end);
|
||||
break;
|
||||
}
|
||||
byte b = src[pos];
|
||||
Object o = trie.Match_bgn_w_byte(b, src, pos, end);
|
||||
if (o == null) { // unknown sequence; word-char
|
||||
Char__add(b, pos);
|
||||
++pos;
|
||||
}
|
||||
else {
|
||||
Xows_text_tkn parser = (Xows_text_tkn)o;
|
||||
pos = parser.Parse(this, src, end, pos, trie.Match_pos());
|
||||
}
|
||||
}
|
||||
}
|
||||
public int Bgn__ws() {return bgn__ws;} private int bgn__ws;
|
||||
public int Bgn__dash() {return bgn__dash;} private int bgn__dash;
|
||||
public int Bgn__slash() {return bgn__slash;} private int bgn__slash;
|
||||
public void Bgn__ws_clear() {this.bgn__ws = -1;}
|
||||
public void Bgn__dash_(int v) {this.bgn__dash = v;}
|
||||
public void Bgn__slash_(int v) {this.bgn__slash= v;}
|
||||
public void Word__add(int bgn__ws, int word_end) {
|
||||
if (bgn__ws == word_end) return; // handle situations like "A!" where sym is at eos
|
||||
if (bgn__ws == -1) return; // handle situations like "A... " where " " is different than "..."
|
||||
byte[] word = dirty ? bfr.Xto_bry_and_clear() : Bry_.Mid(src, bgn__ws, word_end);
|
||||
word_mgr.Add(word);
|
||||
if (bgn__dash != -1) {
|
||||
word_mgr.Add(Bry_.Mid(src, bgn__dash, word_end));
|
||||
bgn__dash = -1;
|
||||
}
|
||||
}
|
||||
public void Char__add(byte b, int pos) {
|
||||
if (dirty)
|
||||
bfr.Add_byte(b);
|
||||
else {
|
||||
if (bgn__ws == -1)
|
||||
bgn__ws = pos;
|
||||
}
|
||||
}
|
||||
public boolean Ws__is_word_end(int pos) {return parser__ws.Is_word_end(src, end, pos);}
|
||||
}
|
||||
class Xob_word_mgr {
|
||||
private final Ordered_hash hash = Ordered_hash_.new_bry_();
|
||||
public void Clear() {hash.Clear();}
|
||||
public int Len() {return hash.Count();}
|
||||
public Xob_word_itm Get_at(int i) {return (Xob_word_itm)hash.Get_at(i);}
|
||||
public void Add(byte[] word) {
|
||||
Xob_word_itm itm = (Xob_word_itm)hash.Get_by(word);
|
||||
if (itm == null) {
|
||||
itm = new Xob_word_itm(word);
|
||||
hash.Add(word, itm);
|
||||
}
|
||||
itm.Count_add_1_();
|
||||
}
|
||||
}
|
||||
class Xob_word_itm {
|
||||
public Xob_word_itm(byte[] word) {
|
||||
this.word = word;
|
||||
this.count = 0;
|
||||
}
|
||||
public byte[] Word() {return word;} private final byte[] word;
|
||||
public int Count() {return count;} private int count; public void Count_add_1_() {++count;}
|
||||
@gplx.Internal protected Xob_word_itm Count_(int v) {this.count = v; return this;}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.search.*;
|
||||
import org.junit.*; import gplx.xowa.langs.cases.*;
|
||||
public class Xows_text_parser__v2_tst {
|
||||
private final Xows_text_parser__v2_fxt fxt = new Xows_text_parser__v2_fxt();
|
||||
@Before public void init() {fxt.Init();}
|
||||
@Test public void Word__one() {
|
||||
fxt.Clear().Test_split("abcd", "abcd");
|
||||
}
|
||||
@Test public void Word__many() {
|
||||
fxt.Clear().Test_split("abc d ef", "abc", "d", "ef");
|
||||
}
|
||||
@Test public void Ws__many() {
|
||||
fxt.Clear().Test_split("a b", "a", "b");
|
||||
}
|
||||
@Test public void Ws__bgn() {
|
||||
fxt.Clear().Test_split(" a", "a");
|
||||
}
|
||||
@Test public void Ws__end() {
|
||||
fxt.Clear().Test_split(" a", "a");
|
||||
}
|
||||
@Test public void Under() {
|
||||
fxt.Clear().Test_split("a_b", "a", "b");
|
||||
}
|
||||
@Test public void Lowercase() {
|
||||
fxt.Clear().Test_split("A B C", "a", "b", "c");
|
||||
}
|
||||
@Test public void Dupe() {
|
||||
fxt.Clear().Test_split("a a a", fxt.Make_word("a", 3));
|
||||
}
|
||||
@Test public void Dupe__lowercase() {
|
||||
fxt.Clear().Test_split("a A", fxt.Make_word("a", 2));
|
||||
}
|
||||
@Test public void Dot__acronym() { // EX: "History of U.S.A. Science "
|
||||
fxt.Clear().Test_split("abc D.E.F. ghi", "abc", "d.e.f.", "ghi");
|
||||
}
|
||||
@Test public void Dot__initials() { // EX: "H. G. Wells"
|
||||
fxt.Clear().Test_split("a. b. cde", "a.", "b.", "cde");
|
||||
}
|
||||
@Test public void Dot__abrv() { // EX: "vs.", "no."
|
||||
fxt.Clear().Test_split("a vs. b", "a", "vs.", "b");
|
||||
}
|
||||
@Test public void Dot__internet() { // EX: "en.wikipedia.org"
|
||||
fxt.Clear().Test_split("a.com", "a.com");
|
||||
}
|
||||
@Test public void Ellipsis__basic() { // EX: "Nights into Dreams..."
|
||||
fxt.Clear().Test_split("a... bc d", "a", "...", "bc", "d");
|
||||
}
|
||||
@Test public void Ellipsis__bgn() {
|
||||
fxt.Clear().Test_split("...a", "...", "a");
|
||||
}
|
||||
@Test public void Ellipsis__end() {
|
||||
fxt.Clear().Test_split("a...", "a", "...");
|
||||
}
|
||||
@Test public void Ellipsis__no_ws() {
|
||||
fxt.Clear().Test_split("a...b", "a", "...", "b");
|
||||
}
|
||||
@Test public void Apos__contraction() { // EX: "I'm"
|
||||
fxt.Clear().Test_split("i'm", "i'm");
|
||||
}
|
||||
@Test public void Apos__multiple() {
|
||||
fxt.Clear().Test_split("a''b", "a''b");
|
||||
}
|
||||
@Test public void Apos__possessive_singular_eos() {// EX: "wiki's"
|
||||
fxt.Clear().Test_split("a's", "a", "a's");
|
||||
}
|
||||
@Test public void Apos__possessive_singular_word() {
|
||||
fxt.Clear().Test_split("a's b", "a", "a's", "b");
|
||||
}
|
||||
@Test public void Apos__possessive_plural_eos() {// EX: "wiki'"
|
||||
fxt.Clear().Test_split("a'", "a", "a'");
|
||||
}
|
||||
@Test public void Apos__possessive_plural_word() {
|
||||
fxt.Clear().Test_split("a' b", "a", "a'", "b");
|
||||
}
|
||||
@Test public void Bang__lone() {
|
||||
fxt.Clear().Test_split("! a", "a");
|
||||
}
|
||||
@Test public void Bang__word() {
|
||||
fxt.Clear().Test_split("a!", "a");
|
||||
}
|
||||
@Test public void Bang__sentence() {// EX: "A!"
|
||||
fxt.Clear().Test_split("a b!", "a", "b");
|
||||
}
|
||||
@Test public void Question__sentence() {// EX: "A?"
|
||||
fxt.Clear().Test_split("a?", "a");
|
||||
}
|
||||
@Test public void Parens_both() {// EX: "A (letter)"
|
||||
fxt.Clear().Test_split("a (b)", "a", "b");
|
||||
}
|
||||
@Test public void Slash__word() {// EX: "Good_cop/bad_cop"
|
||||
fxt.Clear().Test_split("a/b", "a", "b");
|
||||
}
|
||||
// apos: 'Some apostrophe sentence' ?
|
||||
}
|
||||
class Xows_text_parser__v2_fxt {
|
||||
private final Xows_text_parser__v2 word_parser = new Xows_text_parser__v2();
|
||||
private final Xob_word_mgr word_mgr = new Xob_word_mgr();
|
||||
private final Bry_bfr tmp_bfr = Bry_bfr.new_(32);
|
||||
private Xol_case_mgr case_mgr;
|
||||
public void Init() {
|
||||
case_mgr = Xol_case_mgr_.Ascii();
|
||||
word_parser.Init_for_ttl(word_mgr, case_mgr);
|
||||
}
|
||||
public Xows_text_parser__v2_fxt Clear() {
|
||||
word_mgr.Clear();
|
||||
return this;
|
||||
}
|
||||
public Xob_word_itm Make_word(String raw, int count) {return new Xob_word_itm(Bry_.new_u8(raw)).Count_(count);}
|
||||
public void Test_split(String src, String... expd_words) {
|
||||
int len = expd_words.length;
|
||||
Xob_word_itm[] ary = new Xob_word_itm[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
ary[i] = Make_word(expd_words[i], 1);
|
||||
}
|
||||
Test_split(src, ary);
|
||||
}
|
||||
public void Test_split(String src, Xob_word_itm... expd_words) {
|
||||
byte[] src_bry = Bry_.new_u8(src);
|
||||
word_parser.Parse(src_bry, src_bry.length, 0, src_bry.length);
|
||||
Tfds.Eq_str_lines(To_str(expd_words), To_str(word_mgr));
|
||||
}
|
||||
private String To_str(Xob_word_itm[] word_ary) {
|
||||
int len = word_ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if (i != 0) tmp_bfr.Add_byte_nl();
|
||||
Xob_word_itm word = word_ary[i];
|
||||
tmp_bfr.Add(word.Word()).Add_byte_pipe();
|
||||
tmp_bfr.Add_int_variable(word.Count());
|
||||
}
|
||||
return tmp_bfr.Xto_str_and_clear();
|
||||
}
|
||||
private String To_str(Xob_word_mgr word_mgr) {
|
||||
int len = word_mgr.Len();
|
||||
Xob_word_itm[] ary = new Xob_word_itm[len];
|
||||
for (int i = 0; i < len; ++i)
|
||||
ary[i] = word_mgr.Get_at(i);
|
||||
return To_str(ary);
|
||||
}
|
||||
}
|
||||
@@ -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.specials.search.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.search.*;
|
||||
import gplx.core.btries.*; import gplx.core.primitives.*;
|
||||
interface Xows_text_tkn {
|
||||
int Parse(Xows_text_parser__v2 mgr, byte[] src, int src_end, int tkn_bgn, int tkn_end);
|
||||
}
|
||||
class Xows_text_tkn__split implements Xows_text_tkn {
|
||||
private final boolean add_sym_as_word;
|
||||
private final Btrie_slim_mgr trie = Btrie_slim_mgr.cs_();
|
||||
public Xows_text_tkn__split(boolean add_sym_as_word, byte[][] ary) {
|
||||
this.add_sym_as_word = add_sym_as_word;
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
byte[] itm = ary[i];
|
||||
trie.Add_obj(itm, Int_obj_val.new_(itm.length));
|
||||
}
|
||||
}
|
||||
public int Parse(Xows_text_parser__v2 mgr, byte[] src, int src_end, int tkn_bgn, int tkn_end) {
|
||||
if (mgr.Bgn__ws() != -1) // pending word
|
||||
mgr.Word__add(mgr.Bgn__ws(), tkn_bgn); // make word; EX: "B" in "A B C"
|
||||
mgr.Bgn__ws_clear();
|
||||
if (add_sym_as_word)
|
||||
mgr.Word__add(tkn_bgn, tkn_end);
|
||||
int rv = tkn_end;
|
||||
while (rv < src_end) { // skip ws; EX: "a b"
|
||||
byte b = src[rv];
|
||||
Object o = trie.Match_bgn_w_byte(b, src, rv, src_end);
|
||||
if (o == null) break;
|
||||
Int_obj_val itm_len = (Int_obj_val)o;
|
||||
rv += itm_len.Val();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public boolean Is_word_end(byte[] src, int end, int pos) {
|
||||
if (pos >= end) return true;
|
||||
byte b = src[pos];
|
||||
Object o = trie.Match_bgn_w_byte(b, src, pos, end);
|
||||
return o != null;
|
||||
}
|
||||
public static Xows_text_tkn__split new_(Btrie_slim_mgr trie, boolean add_sym_as_word, String... str_ary) {
|
||||
byte[][] bry_ary = Bry_.Ary(str_ary);
|
||||
Xows_text_tkn__split rv = new Xows_text_tkn__split(add_sym_as_word, bry_ary);
|
||||
int len = bry_ary.length;
|
||||
for (int i = 0; i < len; ++i)
|
||||
trie.Add_obj(bry_ary[i], rv);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
class Xows_text_tkn__ellipsis implements Xows_text_tkn {
|
||||
private final byte ellipsis_byte;
|
||||
public Xows_text_tkn__ellipsis(byte ellipsis_byte) {
|
||||
this.ellipsis_byte = ellipsis_byte;
|
||||
}
|
||||
public int Parse(Xows_text_parser__v2 mgr, byte[] src, int src_end, int tkn_bgn, int tkn_end) {
|
||||
int bgn__ws = mgr.Bgn__ws();
|
||||
if (bgn__ws != -1) {
|
||||
mgr.Word__add(bgn__ws, tkn_bgn); // add word; EX: "Dreams" in "Dreams..."
|
||||
mgr.Bgn__ws_clear(); // clear ws flag, else space will create word; EX: "A... B"
|
||||
}
|
||||
int rv = Bry_finder.Find_fwd_while(src, tkn_end, src_end, ellipsis_byte);
|
||||
mgr.Word__add(tkn_bgn, rv); // add ellipssis
|
||||
return rv;
|
||||
}
|
||||
public static Xows_text_tkn new_(Btrie_slim_mgr trie, String ellipsis) {
|
||||
byte[] bry = Bry_.new_u8(ellipsis);
|
||||
Xows_text_tkn rv = new Xows_text_tkn__ellipsis(Bry_.Get_at_end_or_fail(bry));
|
||||
trie.Add_obj(bry, rv);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
class Xows_text_tkn__apos implements Xows_text_tkn {
|
||||
private final byte possessive_byte;
|
||||
public Xows_text_tkn__apos(byte possessive_byte) {this.possessive_byte = possessive_byte;}
|
||||
public int Parse(Xows_text_parser__v2 mgr, byte[] src, int src_end, int tkn_bgn, int tkn_end) {
|
||||
int rv = tkn_end;
|
||||
byte apos_mode = Apos_contraction;
|
||||
if (tkn_end == src_end) { // EX: "A'<EOS>"
|
||||
apos_mode = Apos_possessive_plural;
|
||||
rv = src_end;
|
||||
}
|
||||
else if (mgr.Ws__is_word_end(tkn_end)) { // EX: "A' "
|
||||
apos_mode = Apos_possessive_plural;
|
||||
rv = tkn_end;
|
||||
}
|
||||
else if ( src[tkn_end] == possessive_byte // EX: "A's "
|
||||
&& mgr.Ws__is_word_end(tkn_end + 1))
|
||||
{
|
||||
apos_mode = Apos_possessive_singular;
|
||||
rv = tkn_end + 1;
|
||||
}
|
||||
switch (apos_mode) {
|
||||
case Apos_possessive_plural:
|
||||
case Apos_possessive_singular:
|
||||
int word_bgn = mgr.Bgn__ws();
|
||||
mgr.Word__add(word_bgn, tkn_bgn); // add noun; EX: "wiki";
|
||||
mgr.Word__add(word_bgn, rv); // add full; EX: "wiki's"
|
||||
mgr.Bgn__ws_clear();
|
||||
return rv;
|
||||
case Apos_contraction:
|
||||
break;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private static final byte Apos_contraction = 1, Apos_possessive_plural = 2, Apos_possessive_singular = 3;
|
||||
public static Xows_text_tkn new_(Btrie_slim_mgr trie, String apos, byte possessive_byte) {
|
||||
byte[] bry = Bry_.new_u8(apos);
|
||||
Xows_text_tkn rv = new Xows_text_tkn__apos(possessive_byte);
|
||||
trie.Add_obj(bry, rv);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
// class Xows_text_tkn__slash : Xows_text_tkn {
|
||||
// public int Parse(Xows_text_parser__v2 mgr, byte[] src, int src_end, int tkn_bgn, int tkn_end) {
|
||||
// int bgn__dash = mgr.Bgn__dash();
|
||||
// // add part;
|
||||
// int part_bgn = mgr.Bgn__dash();
|
||||
// if (part_bgn == -1) // no dash
|
||||
// part_bgn = mgr.Bgn__ws();
|
||||
// if (part_bgn != -1)
|
||||
// mgr.Word__add(part_bgn, tkn_bgn); // add word; EX: "a" in "a-b"
|
||||
// mgr.Bgn__dash_(tkn_end);
|
||||
// return tkn_end;
|
||||
// }
|
||||
// public static Xows_text_tkn new_(Btrie_slim_mgr trie, String dash) {
|
||||
// byte[] bry = Bry_.new_u8(dash);
|
||||
// Xows_text_tkn rv = new Xows_text_tkn__slash();
|
||||
// trie.Add_obj(bry, rv);
|
||||
// return rv;
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search.parsers_old; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.search.*;
|
||||
public class Xow_search_parser {
|
||||
private Xow_search_parser_ctx parse_ctx = new Xow_search_parser_ctx(); private byte[] src;
|
||||
public Xows_db_matcher Parse(byte[] src) {
|
||||
this.src = src;
|
||||
Xow_search_tkn[] tkns = new Xow_search_scanner().Scan(src);
|
||||
return Parse_itm_or(parse_ctx.Init(tkns));
|
||||
}
|
||||
private Xows_db_matcher Parse_itm_or(Xow_search_parser_ctx parse_ctx) {
|
||||
Xows_db_matcher lhs = Parse_itm_and(parse_ctx);
|
||||
while (parse_ctx.Cur_tid(Xow_search_tkn.Tid_or)) {
|
||||
parse_ctx.Move_next();
|
||||
Xows_db_matcher rhs = Parse_itm_and(parse_ctx);
|
||||
lhs = new_join(Xows_db_matcher.Tid_or, lhs, rhs);
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
private Xows_db_matcher Parse_itm_and(Xow_search_parser_ctx parse_ctx) {
|
||||
Xows_db_matcher lhs = Parse_itm_not(parse_ctx);
|
||||
while (parse_ctx.Cur_tid(Xow_search_tkn.Tid_and)) {
|
||||
parse_ctx.Move_next();
|
||||
Xows_db_matcher rhs = Parse_itm_not(parse_ctx);
|
||||
lhs = new_join(Xows_db_matcher.Tid_and, lhs, rhs);
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
private Xows_db_matcher Parse_itm_not(Xow_search_parser_ctx parse_ctx) {
|
||||
Xows_db_matcher lhs = Parse_itm_leaf(parse_ctx);
|
||||
while (parse_ctx.Cur_tid(Xow_search_tkn.Tid_not)) {
|
||||
parse_ctx.Move_next();
|
||||
Xows_db_matcher rhs = Parse_itm_leaf(parse_ctx);
|
||||
lhs = new_join(Xows_db_matcher.Tid_not, null, rhs);
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
private Xows_db_matcher Parse_itm_leaf(Xow_search_parser_ctx parse_ctx) {
|
||||
if (parse_ctx.Cur_tid(Xow_search_tkn.Tid_paren_bgn)) {
|
||||
parse_ctx.Move_next();
|
||||
Xows_db_matcher lhs = Parse_itm_or(parse_ctx);
|
||||
if (parse_ctx.Cur_tid(Xow_search_tkn.Tid_paren_end)) parse_ctx.Move_next(); // skip token
|
||||
return lhs;
|
||||
}
|
||||
else if (parse_ctx.Cur_tid(Xow_search_tkn.Tid_eos))
|
||||
return Xows_db_matcher.Null;
|
||||
else {
|
||||
Xow_search_tkn word_tkn = parse_ctx.Move_next();
|
||||
if (word_tkn.Tid() == Xow_search_tkn.Tid_not) {
|
||||
word_tkn = parse_ctx.Move_next();
|
||||
if (word_tkn == null) return Xows_db_matcher.Null; // occurs in "a -"
|
||||
Xows_db_matcher word_itm = new_word(word_tkn, src);
|
||||
return new_join(Xows_db_matcher.Tid_not, null, word_itm);
|
||||
}
|
||||
else
|
||||
return new_word(word_tkn, src);
|
||||
}
|
||||
}
|
||||
private static Xows_db_matcher new_word(Xow_search_tkn tkn, byte[] src) {
|
||||
int tid = tkn.Tid() == Xow_search_tkn.Tid_word ? Xows_db_matcher.Tid_word : Xows_db_matcher.Tid_word_quote;
|
||||
return new Xows_db_matcher(tid, tkn.Val(src), null, null);
|
||||
}
|
||||
private static Xows_db_matcher new_join(int tid, Xows_db_matcher lhs, Xows_db_matcher rhs) {return new Xows_db_matcher(tid, null, lhs, rhs);}
|
||||
}
|
||||
class Xow_search_parser_ctx {
|
||||
private Xow_search_tkn[] ary; private int pos = 0; private int ary_len;
|
||||
public Xow_search_parser_ctx Init(Xow_search_tkn[] ary) {
|
||||
this.ary = ary;
|
||||
this.ary_len = ary.length;
|
||||
this.pos = 0;
|
||||
return this;
|
||||
}
|
||||
public boolean Cur_tid(byte tid) {return pos < ary_len ? tid == ary[pos].Tid(): tid == Xow_search_tkn.Tid_eos;}
|
||||
public Xow_search_tkn Move_next() {
|
||||
Xow_search_tkn rv = null;
|
||||
if (pos < ary_len) rv = ary[pos++];
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search.parsers_old; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.search.*;
|
||||
import gplx.core.primitives.*; import gplx.core.btries.*;
|
||||
class Xow_search_scanner {
|
||||
private final List_adp tkns = List_adp_.new_(); private byte[] src; private int src_len, pos, txt_bgn;
|
||||
private final Ordered_hash tmp_list = Ordered_hash_.new_(); private final Bry_bfr tmp_bfr = Bry_bfr.new_();
|
||||
public Xow_search_tkn[] Scan(byte[] src) {
|
||||
this.src = src; this.src_len = src.length;
|
||||
tkns.Clear(); pos = 0; txt_bgn = -1;
|
||||
while (pos < src_len) {
|
||||
byte cur_b = src[pos];
|
||||
Object cur_obj = trie.Match_bgn_w_byte(cur_b, src, pos, src_len);
|
||||
if (cur_obj == null) { // text character
|
||||
if (txt_bgn == -1) txt_bgn = pos; // 1st character not set; set it
|
||||
++pos;
|
||||
}
|
||||
else { // AND, OR, (, ), -, \s, "
|
||||
int pos_end = trie.Match_pos();
|
||||
byte cur_tid = ((Byte_obj_val)cur_obj).Val();
|
||||
if (Cur_join_is_word(cur_tid, pos_end)) continue; // ignore words containing "and", "or"; EX: "random"; "for"
|
||||
if (txt_bgn != -1) { // pending word; create
|
||||
Tkns_add_word(Xow_search_tkn.Tid_word, txt_bgn, pos);
|
||||
txt_bgn = -1;
|
||||
}
|
||||
switch (cur_tid) {
|
||||
case Xow_search_tkn.Tid_space: // discard spaces
|
||||
pos = Bry_finder.Find_fwd_while(src, pos, src_len, Byte_ascii.Space);
|
||||
break;
|
||||
case Xow_search_tkn.Tid_quote: // find end quote and add as word
|
||||
int quote_bgn = pos + 1;
|
||||
int quote_end = Bry_finder.Find_fwd(src, Byte_ascii.Quote, quote_bgn, src_len);
|
||||
if (quote_end == Bry_.NotFound) throw Exc_.new_("could not find end quote", "src", String_.new_u8(src));
|
||||
Tkns_add_word(Xow_search_tkn.Tid_word_quoted, quote_bgn, quote_end);
|
||||
pos = quote_end + 1; // +1 to place after quote
|
||||
break;
|
||||
case Xow_search_tkn.Tid_not:
|
||||
Tkns_add_word(Xow_search_tkn.Tid_not, pos, pos_end);
|
||||
pos = pos_end;
|
||||
break;
|
||||
case Xow_search_tkn.Tid_paren_bgn: case Xow_search_tkn.Tid_paren_end:
|
||||
case Xow_search_tkn.Tid_and: case Xow_search_tkn.Tid_or:
|
||||
tkns.Add(new_tkn(cur_tid, pos, pos_end));
|
||||
pos = pos_end;
|
||||
break;
|
||||
default: throw Exc_.new_unhandled(cur_tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (txt_bgn != -1) { // pending word; create
|
||||
Tkns_add_word(Xow_search_tkn.Tid_word, txt_bgn, pos);
|
||||
txt_bgn = -1;
|
||||
}
|
||||
return (Xow_search_tkn[])tkns.To_ary_and_clear(Xow_search_tkn.class);
|
||||
}
|
||||
private boolean Cur_join_is_word(byte cur_tid, int pos_end) { // extra logic to handle and / or occuring in unquoted strings; EX: "random"; "for"
|
||||
switch (cur_tid) {
|
||||
default: return false; // only look at AND, OR, -
|
||||
case Xow_search_tkn.Tid_and: case Xow_search_tkn.Tid_or: case Xow_search_tkn.Tid_not:
|
||||
break;
|
||||
}
|
||||
boolean join_is_word = true;
|
||||
if (txt_bgn == -1) { // no pending word;
|
||||
if (cur_tid == Xow_search_tkn.Tid_not) return false; // NOT is only operator if no pending tkn; EX: -abc -> NOT abc; a-b -> a-b
|
||||
byte nxt_b = pos_end < src_len ? src[pos_end] : Byte_ascii.Nil;
|
||||
Object nxt_obj = trie.Match_bgn_w_byte(nxt_b, src, pos_end, src_len);
|
||||
if (nxt_obj == null) // next tkn is text; join must be word
|
||||
join_is_word = true;
|
||||
else { // next tkn is tkn
|
||||
byte nxt_tid = ((Byte_obj_val)nxt_obj).Val();
|
||||
switch (nxt_tid) {
|
||||
case Xow_search_tkn.Tid_space: case Xow_search_tkn.Tid_quote:
|
||||
case Xow_search_tkn.Tid_paren_bgn: case Xow_search_tkn.Tid_paren_end:
|
||||
join_is_word = false; // next tkn is sym; and/or is not word; EX: a AND ; a AND"b"; a AND(b)
|
||||
break;
|
||||
case Xow_search_tkn.Tid_not: case Xow_search_tkn.Tid_and: case Xow_search_tkn.Tid_or:
|
||||
join_is_word = true; // next tkn is and or not; and/or is word; EX: andor; oror; or-abc;
|
||||
break;
|
||||
default: throw Exc_.new_unhandled(cur_tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // pending word; cur join must be word; EX: "grand": "and" invoked and "gr" pending
|
||||
join_is_word = true;
|
||||
}
|
||||
if (join_is_word) {
|
||||
if (txt_bgn == -1) txt_bgn = pos; // 1st character not set; set it
|
||||
pos = pos_end;
|
||||
return true;
|
||||
}
|
||||
if (txt_bgn != -1) {
|
||||
Tkns_add_word(Xow_search_tkn.Tid_word, txt_bgn, pos); // create word
|
||||
txt_bgn = -1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private void Tkns_add_word(byte tid, int src_bgn, int src_end) {
|
||||
if (tkns.Count() > 0) { // at least 1 tkn; check for "auto-and"
|
||||
Xow_search_tkn last_tkn = (Xow_search_tkn)tkns.Get_at_last();
|
||||
if (last_tkn.Tid() == Xow_search_tkn.Tid_word) // previous tkn is word; auto "AND" words; EX: A B -> A AND B
|
||||
tkns.Add(Xow_search_tkn.new_bry(Xow_search_tkn.Tid_and, Bry_and));
|
||||
}
|
||||
if (tid == Xow_search_tkn.Tid_word) { // if word has symbol, convert to quoted; EX: a-b should become "a-b"; otherwise searcher would search for a single word a-b
|
||||
byte[] cur_word = Bry_.Mid(src, src_bgn, src_end);
|
||||
byte[][] words = gplx.xowa.bldrs.cmds.texts.Xob_search_base.Split_ttl_into_words(null, tmp_list, tmp_bfr, cur_word);
|
||||
int words_len = words.length;
|
||||
if ( words_len == 1 // only one word
|
||||
&& !Bry_.Eq(words[0], cur_word) // split word not same as raw
|
||||
&& Bry_finder.Find_fwd(cur_word, Byte_ascii.Star) == -1 // no asterisk
|
||||
) {
|
||||
tkns.Add(Xow_search_tkn.new_bry(tid, words[0]));
|
||||
return;
|
||||
}
|
||||
if (words.length > 1) // multiple words; add as quoted-term; EX: "a-b"
|
||||
tid = Xow_search_tkn.Tid_word_quoted;
|
||||
}
|
||||
tkns.Add(new_tkn(tid, src_bgn, src_end));
|
||||
}
|
||||
private Xow_search_tkn new_tkn(byte tid, int val_bgn, int val_end) {return Xow_search_tkn.new_pos(tid, val_bgn, val_end);}
|
||||
private static final byte[] Bry_and = Bry_.new_a7("AND");
|
||||
private static final Btrie_slim_mgr trie = Btrie_slim_mgr.ci_ascii_()// NOTE:ci.ascii:OR / AND only
|
||||
.Add_str_byte(" " , Xow_search_tkn.Tid_space)
|
||||
.Add_str_byte("\"" , Xow_search_tkn.Tid_quote)
|
||||
.Add_str_byte("-" , Xow_search_tkn.Tid_not)
|
||||
.Add_str_byte("(" , Xow_search_tkn.Tid_paren_bgn)
|
||||
.Add_str_byte(")" , Xow_search_tkn.Tid_paren_end)
|
||||
.Add_str_byte("or" , Xow_search_tkn.Tid_or)
|
||||
.Add_str_byte("and" , Xow_search_tkn.Tid_and);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search.parsers_old; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.search.*;
|
||||
class Xow_search_tkn {
|
||||
private final int val_bgn, val_end;
|
||||
private final byte[] val_bry;
|
||||
Xow_search_tkn(byte tid, int val_bgn, int val_end, byte[] val_bry) {this.tid = tid; this.val_bgn = val_bgn; this.val_end = val_end; this.val_bry = val_bry;}
|
||||
public byte Tid() {return tid;} private final byte tid;
|
||||
public byte[] Val(byte[] src) {return val_bry == null ? Bry_.Mid(src, val_bgn, val_end) : val_bry;}
|
||||
public static Xow_search_tkn new_pos(byte tid, int val_bgn, int val_end) {return new Xow_search_tkn(tid, val_bgn, val_end, null);}
|
||||
public static Xow_search_tkn new_bry(byte tid, byte[] val_bry) {return new Xow_search_tkn(tid, -1, -1, val_bry);}
|
||||
public static final byte
|
||||
Tid_root = 1
|
||||
, Tid_word = 2
|
||||
, Tid_word_quoted = 3
|
||||
, Tid_space = 4
|
||||
, Tid_quote = 5
|
||||
, Tid_not = 6
|
||||
, Tid_paren_bgn = 7
|
||||
, Tid_paren_end = 8
|
||||
, Tid_or = 9
|
||||
, Tid_and = 10
|
||||
, Tid_eos = 11
|
||||
;
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.statistics; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.xowa.langs.numbers.*;
|
||||
public class Xop_statistics_page implements Xows_page {
|
||||
private Xop_statistics_stats_page_grp stats_page = new Xop_statistics_stats_page_grp();
|
||||
// private Xop_statistics_stats_wiki_grp stats_wiki = new Xop_statistics_stats_wiki_grp();
|
||||
private Xop_statistics_stats_ns_grp stats_ns = new Xop_statistics_stats_ns_grp();
|
||||
public Xows_special_meta Special_meta() {return Xows_special_meta_.Itm__statistics;}
|
||||
public void Special_gen(Xowe_wiki wiki, Xoae_page page, Xoa_url url, Xoa_ttl ttl) {
|
||||
byte[] html = Build_html(wiki);
|
||||
page.Html_data().Html_restricted_n_(); // [[Special:]] pages allow all HTML
|
||||
page.Data_raw_(html);
|
||||
}
|
||||
public byte[] Build_html(Xowe_wiki wiki) {
|
||||
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_m001();
|
||||
stats_page.Wiki_(wiki);
|
||||
// stats_wiki.Wiki_(wiki);
|
||||
stats_ns.Wiki_(wiki);
|
||||
fmtr_all.Bld_bfr_many(tmp_bfr, stats_page, stats_ns);
|
||||
return tmp_bfr.To_bry_and_rls();
|
||||
}
|
||||
private Bry_fmtr fmtr_all = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( "<div id=\"mw-content-text\">"
|
||||
, "<table class=\"wikitable mw-statistics-table\">~{page_stats}~{ns_stats}"
|
||||
, "</table>"
|
||||
, "</div>"
|
||||
), "page_stats", "ns_stats");
|
||||
}
|
||||
class Xop_statistics_stats_page_grp implements Bry_fmtr_arg {
|
||||
public void Wiki_(Xowe_wiki v) {this.wiki = v;} private Xowe_wiki wiki;
|
||||
public void XferAry(Bry_bfr bfr, int idx) {
|
||||
byte[] lbl_header_pages = wiki.Msg_mgr().Val_by_id(Xol_msg_itm_.Id_statistics_header_pages);
|
||||
byte[] lbl_articles = wiki.Msg_mgr().Val_by_id(Xol_msg_itm_.Id_statistics_articles);
|
||||
byte[] lbl_pages = wiki.Msg_mgr().Val_by_id(Xol_msg_itm_.Id_statistics_pages);
|
||||
byte[] lbl_pages_desc = wiki.Msg_mgr().Val_by_id(Xol_msg_itm_.Id_statistics_pages_desc);
|
||||
Xol_num_mgr num_mgr = wiki.Lang().Num_mgr();
|
||||
fmtr_page.Bld_bfr_many(bfr, lbl_header_pages, lbl_articles, lbl_pages, lbl_pages_desc , num_mgr.Format_num(wiki.Stats().NumArticles()), num_mgr.Format_num(wiki.Stats().NumPages()));
|
||||
}
|
||||
private Bry_fmtr fmtr_page = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( ""
|
||||
, " <tr>"
|
||||
, " <th colspan=\"2\">~{lbl_header_pages}</th>"
|
||||
, " </tr>"
|
||||
, " <tr class=\"mw-statistics-articles\">"
|
||||
, " <td>~{lbl_articles}</td>"
|
||||
, " <td class=\"mw-statistics-numbers\" style='text-align:right'>~{page_count_main}</td>"
|
||||
, " </tr>"
|
||||
, " <tr class=\"mw-statistics-pages\">"
|
||||
, " <td>~{lbl_pages}<br /><small class=\"mw-statistic-desc\"> ~{lbl_pages_desc}</small></td>"
|
||||
, " <td class=\"mw-statistics-numbers\" style='text-align:right'>~{page_count_all}</td>"
|
||||
, " </tr>"
|
||||
), "lbl_header_pages", "lbl_articles", "lbl_pages", "lbl_pages_desc", "page_count_main", "page_count_all");
|
||||
}
|
||||
class Xop_statistics_stats_ns_grp implements Bry_fmtr_arg {
|
||||
private Xop_statistics_stats_ns_itm ns_itm_fmtr = new Xop_statistics_stats_ns_itm();
|
||||
public void Wiki_(Xowe_wiki v) {this.wiki = v; ns_itm_fmtr.Wiki_(v);} private Xowe_wiki wiki;
|
||||
public void XferAry(Bry_bfr bfr, int idx) {
|
||||
byte[] lbl_header_ns = wiki.Msg_mgr().Val_by_id(Xol_msg_itm_.Id_statistics_header_ns);
|
||||
fmtr_ns_grp.Bld_bfr_many(bfr, lbl_header_ns, ns_itm_fmtr);
|
||||
}
|
||||
private Bry_fmtr fmtr_ns_grp = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( ""
|
||||
, " <tr>"
|
||||
, " <th colspan=\"2\">~{lbl_header_ns}</th>"
|
||||
, " </tr>~{ns_itms}"
|
||||
), "lbl_header_ns", "ns_itms");
|
||||
}
|
||||
class Xop_statistics_stats_ns_itm implements Bry_fmtr_arg {
|
||||
public void Wiki_(Xowe_wiki v) {this.wiki = v;} private Xowe_wiki wiki;
|
||||
public void XferAry(Bry_bfr bfr, int idx) {
|
||||
Xow_ns_mgr ns_mgr = wiki.Ns_mgr();
|
||||
int ns_len = ns_mgr.Count();
|
||||
for (int i = 0; i < ns_len; i++) {
|
||||
Xow_ns ns = ns_mgr.Ids_get_at(i);
|
||||
if (ns.Is_meta()) continue;
|
||||
if (ns.Count() == 0) continue;
|
||||
byte[] ns_name = ns.Id_main() ? wiki.Msg_mgr().Val_by_id(Xol_msg_itm_.Id_ns_blankns) : ns.Name_txt();
|
||||
fmtr_ns_itm.Bld_bfr_many(bfr, ns_name, wiki.Lang().Num_mgr().Format_num(ns.Count()));
|
||||
}
|
||||
}
|
||||
private Bry_fmtr fmtr_ns_itm = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( ""
|
||||
, " <tr>"
|
||||
, " <td>~{ns_name}</td>"
|
||||
, " <td style='text-align:right'>~{ns_count}</td>"
|
||||
, " </tr>"
|
||||
), "ns_name", "ns_count");
|
||||
}
|
||||
class Xop_statistics_stats_wiki_grp implements Bry_fmtr_arg {
|
||||
public void Wiki_(Xowe_wiki v) {this.wiki = v;} private Xowe_wiki wiki;
|
||||
public void XferAry(Bry_bfr bfr, int idx) {
|
||||
fmtr_wiki.Bld_bfr_many(bfr, wiki.Db_mgr().Tid_name(), wiki.Fsys_mgr().Root_dir().Raw(), Byte_.Xto_str(wiki.Db_mgr().Category_version()), wiki.Maint_mgr().Wiki_dump_date().XtoStr_fmt_iso_8561());
|
||||
}
|
||||
private Bry_fmtr fmtr_wiki = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( ""
|
||||
, " <tr>"
|
||||
, " <th colspan=\"2\">Wiki statistics</th>"
|
||||
, " </tr>"
|
||||
, " <tr>"
|
||||
, " <td>Wiki format</td>"
|
||||
, " <td>~{wiki_format}</td>"
|
||||
, " </tr>"
|
||||
, " <tr>"
|
||||
, " <td>Wiki location</td>"
|
||||
, " <td>~{wiki_url}</td>"
|
||||
, " </tr>"
|
||||
, " <tr>"
|
||||
, " <td>Category level</td>"
|
||||
, " <td>~{ctg_version}</td>"
|
||||
, " </tr>"
|
||||
, " <tr>"
|
||||
, " <td>Last page updated on</td>"
|
||||
, " <td>~{page_modified_max}</td>"
|
||||
, " </tr>"
|
||||
), "wiki_format", "wiki_url", "ctg_version", "page_modified_max");
|
||||
}
|
||||
@@ -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.specials.statistics; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import org.junit.*;
|
||||
public class Xop_statistics_page_tst {
|
||||
@Before public void init() {fxt.Clear();} private Xop_statistics_page_fxt fxt = new Xop_statistics_page_fxt();
|
||||
@Test public void Basic() {
|
||||
fxt.Test_html(String_.Concat_lines_nl_skip_last
|
||||
( "<div id=\"mw-content-text\">"
|
||||
, "<table class=\"wikitable mw-statistics-table\">"
|
||||
, " <tr>"
|
||||
, " <th colspan=\"2\">Page statistics</th>"
|
||||
, " </tr>"
|
||||
, " <tr class=\"mw-statistics-articles\">"
|
||||
, " <td>Content pages</td>"
|
||||
, " <td class=\"mw-statistics-numbers\" style='text-align:right'>0</td>"
|
||||
, " </tr>"
|
||||
, " <tr class=\"mw-statistics-pages\">"
|
||||
, " <td>Pages<br /><small class=\"mw-statistic-desc\"> All pages in the wiki, including talk pages, redirects, etc.</small></td>"
|
||||
, " <td class=\"mw-statistics-numbers\" style='text-align:right'>0</td>"
|
||||
, " </tr>"
|
||||
, " <tr>"
|
||||
, " <th colspan=\"2\">Namespace statistics</th>"
|
||||
, " </tr>"
|
||||
, "</table>"
|
||||
, "</div>"
|
||||
));
|
||||
}
|
||||
}
|
||||
class Xop_statistics_page_fxt {
|
||||
public void Clear() {
|
||||
parser_fxt = new Xop_fxt();
|
||||
parser_fxt.Reset();
|
||||
wiki = parser_fxt.Wiki();
|
||||
special_page = wiki.Special_mgr().Page_statistics();
|
||||
} private Xop_fxt parser_fxt; private Xop_statistics_page special_page; private Xowe_wiki wiki;
|
||||
public void Test_html(String expd) {
|
||||
Tfds.Eq_str_lines(expd, String_.new_u8(special_page.Build_html(wiki)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.xowa.bookmarks; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.xowa.*;
|
||||
import gplx.json.*;
|
||||
import gplx.xowa.users.data.*; import gplx.xowa.users.bmks.*;
|
||||
import gplx.xowa.html.xouis.tbls.*; import gplx.xowa.html.xouis.fmtrs.*;
|
||||
public class Xoui_tbl_itm__bmk implements Xoui_tbl_itm {
|
||||
private final Xoud_bmk_itm_tbl tbl;
|
||||
private final Json_wtr json_wtr = new Json_wtr();
|
||||
private final Xoui_cells_fmtr cells_fmtr = new Xoui_cells_fmtr();
|
||||
private final Xoui_val_fmtr edit_val_fmtr = Xoui_val_fmtr_.new_edit();
|
||||
private final Xoui_val_fmtr view_val_fmtr = Xoui_val_fmtr_.new_view();
|
||||
private final Bry_bfr tmp_bfr = Bry_bfr.new_(255);
|
||||
public Xoui_tbl_itm__bmk(Xoud_bmk_itm_tbl tbl) {this.tbl = tbl;}
|
||||
public byte[] Key() {return key;} private static final byte[] key = Bry_.new_a7("bmk");
|
||||
public Xoui_btn_itm[] View_btns() {return view_btns;}
|
||||
public Xoui_btn_itm[] Edit_btns() {return edit_btns;}
|
||||
public Xoui_col_itm[] Cols() {return cols;}
|
||||
public Xoui_row_itm[] Rows() {return rows;} public void Rows_(Xoui_row_itm[] v) {this.rows = v;} private Xoui_row_itm[] rows;
|
||||
public void Del(byte[] row_pkey_bry) {
|
||||
int bmk_id = To_bmk_id(row_pkey_bry);
|
||||
tbl.Delete(bmk_id);
|
||||
}
|
||||
public String Edit(byte[] row_id, byte[] row_pkey_bry) {
|
||||
return Write_cells(edit_val_fmtr, edit_btns, row_id, Get_row_by_pkey(row_pkey_bry));
|
||||
}
|
||||
public String Save(Xow_wiki wiki, byte[] row_id, byte[] row_pkey_bry, Xoui_val_hash hash) {
|
||||
int bmk_id = To_bmk_id(row_pkey_bry);
|
||||
byte[] name = hash.Get_val_as_bry_or_fail(Key_name);
|
||||
byte[] url_bry = hash.Get_val_as_bry_or_fail(Key_url);
|
||||
Xoa_url_parser url_parser = wiki.App().Utl__url_parser();
|
||||
Xoa_url url = url_parser.Parse(url_bry);
|
||||
Xoui_row_itm row_itm = Get_row_by_pkey(row_pkey_bry);
|
||||
Set_vals(tmp_bfr, row_itm.Vals(), name, url_bry);
|
||||
tbl.Update(bmk_id, -1, -1, name, url.Wiki_bry(), url_bry, Bry_.Empty);
|
||||
return Write_cells(view_val_fmtr, view_btns, row_id, row_itm);
|
||||
}
|
||||
public void Set_order_adj(byte[] row_pkey, boolean adj_down) {throw Exc_.new_unimplemented();}
|
||||
|
||||
private int To_bmk_id(byte[] row_pkey_bry) {return Bry_.Xto_int_or_fail(row_pkey_bry);}
|
||||
private Xoui_row_itm Get_row_by_pkey(byte[] row_pkey_bry) {
|
||||
int len = rows.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Xoui_row_itm row = rows[i];
|
||||
if (Bry_.Eq(row.Pkey(), row_pkey_bry)) return row;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private String Write_cells(Xoui_val_fmtr val_fmtr, Xoui_btn_itm[] btns, byte[] row_id, Xoui_row_itm row) {
|
||||
cells_fmtr.Ctor(val_fmtr, btns);
|
||||
cells_fmtr.Init(row_id, row);
|
||||
cells_fmtr.XferAry(tmp_bfr, 0);
|
||||
json_wtr.Doc_bgn();
|
||||
json_wtr.Kv_bfr("html", tmp_bfr);
|
||||
json_wtr.Doc_end();
|
||||
return json_wtr.To_str_and_clear();
|
||||
}
|
||||
private static final byte[] Key_name = Bry_.new_a7("name"), Key_url = Bry_.new_a7("url");
|
||||
private static final Xoui_col_itm[] cols = new Xoui_col_itm[]
|
||||
{ new Xoui_col_itm(Xoui_col_itm.Type_id_str, 150, "name" , "Name")
|
||||
, new Xoui_col_itm(Xoui_col_itm.Type_id_str, 350, "url" , "Url")
|
||||
};
|
||||
private static final Xoui_btn_itm[] view_btns = new Xoui_btn_itm[]
|
||||
{ new Xoui_btn_itm("rows__edit" , "edit.png" , "edit")
|
||||
, new Xoui_btn_itm("rows__delete" , "delete.png" , "delete")
|
||||
};
|
||||
private static final Xoui_btn_itm[] edit_btns = new Xoui_btn_itm[]
|
||||
{ new Xoui_btn_itm("rows__save" , "save.png" , "save")
|
||||
, new Xoui_btn_itm("rows__cancel" , "cancel.png" , "cancel")
|
||||
};
|
||||
private static final Bry_fmtr url_fmtr = Bry_fmtr.new_("<a href='/site/~{url}'>~{url}</a>", "url");
|
||||
public static Xoui_tbl_itm new_(Xoud_bmk_itm_tbl dom_tbl, Xoud_bmk_itm_row[] dom_rows) {
|
||||
Xoui_tbl_itm rv = new Xoui_tbl_itm__bmk(dom_tbl);
|
||||
int len = dom_rows.length;
|
||||
Xoui_row_itm[] gui_rows = new Xoui_row_itm[len];
|
||||
Bry_bfr tmp_bfr = Bry_bfr.new_(255);
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Xoud_bmk_itm_row dom_row = dom_rows[i];
|
||||
Xoui_val_itm[] vals = new Xoui_val_itm[2];
|
||||
Set_vals(tmp_bfr, vals, dom_row.Name(), dom_row.Url());
|
||||
Xoui_row_itm gui_row = new Xoui_row_itm(rv, Int_.Xto_bry(dom_row.Id()), vals);
|
||||
gui_rows[i] = gui_row;
|
||||
}
|
||||
rv.Rows_(gui_rows);
|
||||
return rv;
|
||||
}
|
||||
private static void Set_vals(Bry_bfr tmp_bfr, Xoui_val_itm[] vals, byte[] name, byte[] url) {
|
||||
vals[0] = new Xoui_val_itm(name, name);
|
||||
url_fmtr.Bld_bfr_many(tmp_bfr, url);
|
||||
vals[1] = new Xoui_val_itm(url, tmp_bfr.Xto_bry_and_clear());
|
||||
}
|
||||
}
|
||||
@@ -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.specials.xowa.bookmarks; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.xowa.*;
|
||||
import gplx.core.primitives.*;
|
||||
import gplx.xowa.html.xouis.tbls.*;
|
||||
import gplx.xowa.users.data.*; import gplx.xowa.users.bmks.*;
|
||||
public class Xows_bmk_page implements Xows_page {
|
||||
public Xows_special_meta Special_meta() {return Xows_special_meta_.Itm__bookmarks;}
|
||||
public void Special_gen(Xowe_wiki wiki, Xoae_page page, Xoa_url url, Xoa_ttl ttl) {
|
||||
Xoud_bmk_mgr bmk_mgr = wiki.App().User().User_db_mgr().Bmk_mgr();
|
||||
page.Html_data().Module_mgr().Itm__xoui().Init(wiki.Appe()).Enabled_y_();
|
||||
Bry_bfr bfr = wiki.Utl__bfr_mkr().Get_m001();
|
||||
Xoud_bmk_itm_row[] rows = bmk_mgr.Itms__get(Xoud_bmk_mgr.Owner_root);
|
||||
Xoui_tbl_itm hui_tbl = Xoui_tbl_itm__bmk.new_(bmk_mgr.Tbl__itm(), rows);
|
||||
wiki.Html__xoui_tbl_mgr().Write(bfr, hui_tbl);
|
||||
page.Hdump_data().Body_(bfr.To_bry_and_rls());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.xowa.default_tab; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.xowa.*;
|
||||
public class Default_tab_page implements Xows_page {
|
||||
public Xows_special_meta Special_meta() {return Xows_special_meta_.Itm__default_tab;}
|
||||
public void Special_gen(Xowe_wiki wiki, Xoae_page page, Xoa_url url, Xoa_ttl ttl) {
|
||||
page.Data_raw_(Bry_.Empty);
|
||||
page.Html_data().Custom_html_(Bry_.Empty);
|
||||
page.Html_data().Custom_name_(Tab_name_bry);
|
||||
}
|
||||
public static final byte[] Tab_name_bry = Bry_.new_a7("New Tab");
|
||||
}
|
||||
73
400_xowa/src/gplx/xowa/specials/xowa/diags/Db_rdr_utl.java
Normal file
73
400_xowa/src/gplx/xowa/specials/xowa/diags/Db_rdr_utl.java
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.xowa.diags; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.xowa.*;
|
||||
import gplx.dbs.*;
|
||||
import gplx.dbs.engines.mems.*;
|
||||
class Db_rdr_utl {
|
||||
public static void Load_and_write(Db_conn conn, String sql, Bry_bfr bfr) {
|
||||
Write_to_bfr(bfr, Load(conn, sql));
|
||||
}
|
||||
public static Mem_qry_set Load_as_qry_set(Db_conn conn, Db_meta_fld_list fld_list, String sql) {
|
||||
Mem_qry_set qry_set = new Mem_qry_set();
|
||||
DataRdr rdr = conn.Exec_sql_as_rdr(sql);
|
||||
try {
|
||||
int fld_count = rdr.FieldCount();
|
||||
while (rdr.MoveNextPeer()) {
|
||||
Mem_row row = new Mem_row();
|
||||
for (int i = 0; i < fld_count; ++i)
|
||||
row.Add(fld_list.Get_at(i).Name(), rdr.ReadAt(i));
|
||||
qry_set.Add(row);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
rdr.Rls();
|
||||
}
|
||||
return qry_set;
|
||||
}
|
||||
public static Object[][] Load(Db_conn conn, String sql) {
|
||||
List_adp list = List_adp_.new_();
|
||||
DataRdr rdr = conn.Exec_sql_as_rdr(sql);
|
||||
try {
|
||||
int fld_count = rdr.FieldCount();
|
||||
while (rdr.MoveNextPeer()) {
|
||||
Object[] row = new Object[fld_count];
|
||||
for (int i = 0; i < fld_count; ++i) {
|
||||
row[i] = rdr.ReadAt(i);
|
||||
}
|
||||
list.Add(row);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
rdr.Rls();
|
||||
}
|
||||
return (Object[][])list.To_ary_and_clear(Object[].class);
|
||||
}
|
||||
public static void Write_to_bfr(Bry_bfr bfr, Object[][] rows, int... skip) {
|
||||
int rows_len = rows.length;
|
||||
for (int i = 0; i < rows_len; ++i) {
|
||||
Object[] row = (Object[])rows[i];
|
||||
int row_len = row.length;
|
||||
for (int j = 0; j < row_len; ++j) {
|
||||
if (skip != null && Int_.In(j, skip)) continue;
|
||||
Object val = row[j];
|
||||
bfr.Add_obj(val).Add_byte_pipe();
|
||||
}
|
||||
bfr.Add_byte_nl();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.xowa.diags; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.xowa.*;
|
||||
import gplx.fsdb.*; import gplx.fsdb.meta.*;
|
||||
import gplx.xowa.files.origs.*;
|
||||
class Xows_cmd__file_check {
|
||||
private Io_url tmp_dir;
|
||||
public void Exec(Bry_bfr bfr, Xoa_app app, Xoa_url url, Xoa_url_arg_hash arg_hash) {
|
||||
byte[] wiki_bry = arg_hash.Get_val_bry_or(Arg_wiki, null); if (wiki_bry == null) {Xoa_app_.Usr_dlg().Warn_many("", "", "special.cmd; no wiki: url=~{0}", url.Raw()); return;}
|
||||
byte[] file_bry = arg_hash.Get_val_bry_or(Arg_file, null); if (file_bry == null) {Xoa_app_.Usr_dlg().Warn_many("", "", "special.cmd; no file: url=~{0}", url.Raw()); return;}
|
||||
Xow_wiki wiki = app.Wiki_mgri().Get_by_key_or_make_init_y(wiki_bry);
|
||||
tmp_dir = wiki.Fsys_mgr().Tmp_dir();
|
||||
boolean schema_1 = wiki.File__fsdb_core().File__schema_is_1();
|
||||
Fsdb_db_file atr_main = null;
|
||||
try {Write_kv(bfr, "machine.op_sys", Op_sys.Cur().Os_name());} catch (Exception e) {bfr.Add_str_u8(Err_.Message_gplx(e));}
|
||||
try {Write_kv(bfr, "app.version", Xoa_app_.Version);} catch (Exception e) {bfr.Add_str_u8(Err_.Message_gplx(e));}
|
||||
try {Write_kv(bfr, "cfg_file_retrieve", ((Xoae_app)app).File_mgr().Wmf_mgr().Enabled());} catch (Exception e) {bfr.Add_str_u8(Err_.Message_gplx(e));}
|
||||
try {Write_kv(bfr, "fsdb.schema_is_1", schema_1);} catch (Exception e) {bfr.Add_str_u8(Err_.Message_gplx(e));}
|
||||
try {Write_kv(bfr, "fsdb.mnt_file", wiki.File__fsdb_core().File__mnt_file().Url());} catch (Exception e) {bfr.Add_str_u8(Err_.Message_gplx(e));}
|
||||
try {Write_kv(bfr, "fsdb.abc_file", wiki.File__fsdb_core().File__abc_file__at(Fsm_mnt_mgr.Mnt_idx_main).Url());} catch (Exception e) {bfr.Add_str_u8(Err_.Message_gplx(e));}
|
||||
try {
|
||||
atr_main = wiki.File__fsdb_core().File__atr_file__at(Fsm_mnt_mgr.Mnt_idx_main);
|
||||
Write_kv(bfr, "fsdb.atr_file", atr_main.Url());
|
||||
} catch (Exception e) {bfr.Add_str_u8(Err_.Message_gplx(e));}
|
||||
try {Write_kv(bfr, "fsdb.orig", wiki.File__fsdb_core().File__orig_tbl_ary()[0].Conn().Conn_info().Xto_raw());} catch (Exception e) {bfr.Add_str_u8(Err_.Message_gplx(e));}
|
||||
Fsdb_sql_mkr sql_mkr = schema_1 ? Fsdb_sql_mkr__v1.I : Fsdb_sql_mkr__v2.I;
|
||||
String sql = "";
|
||||
try {
|
||||
Xof_orig_tbl orig_tbl = wiki.File__fsdb_core().File__orig_tbl_ary()[0];
|
||||
sql = sql_mkr.Orig_by_ttl(file_bry);
|
||||
Write_sect(bfr, "fsdb.orig.select", sql);
|
||||
Db_rdr_utl.Load_and_write(orig_tbl.Conn(), sql, bfr);
|
||||
} catch (Exception e) {bfr.Add_str_u8(Err_.Message_gplx(e));}
|
||||
Object[][] rows = null;
|
||||
try {
|
||||
sql = sql_mkr.Fil_by_ttl(file_bry);
|
||||
Write_sect(bfr, "fsdb.fil.select", sql);
|
||||
rows = Db_rdr_utl.Load(atr_main.Conn(), sql);
|
||||
Db_rdr_utl.Write_to_bfr(bfr, rows);
|
||||
Write_thms(bfr, file_bry, sql_mkr, wiki.File__mnt_mgr().Mnts__get_main(), atr_main, rows);
|
||||
} catch (Exception e) {bfr.Add_str_u8(Err_.Message_gplx(e));}
|
||||
}
|
||||
private void Write_thms(Bry_bfr bfr, byte[] file_bry, Fsdb_sql_mkr sql_mkr, Fsm_mnt_itm mnt_itm, Fsdb_db_file atr_main, Object[][] rows) {
|
||||
int rows_len = rows.length;
|
||||
for (int i = 0; i < rows_len; ++i) {
|
||||
Object[] row = rows[i];
|
||||
int file_id = Int_.cast_(row[0]);
|
||||
String sql = sql_mkr.Thm_by_id(file_id);
|
||||
Write_sect(bfr, "fsdb.thm.select", sql);
|
||||
Object[][] thm_rows = Db_rdr_utl.Load(atr_main.Conn(), sql);
|
||||
Db_rdr_utl.Write_to_bfr(bfr, thm_rows);
|
||||
Write_bins(bfr, file_bry, sql_mkr, mnt_itm, thm_rows, 0, 6);
|
||||
Object bin_db_id_obj = row[4];
|
||||
if (bin_db_id_obj != null) {
|
||||
Write_bins(bfr, file_bry, sql_mkr, mnt_itm, rows, 0, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void Write_bins(Bry_bfr bfr, byte[] file_bry, Fsdb_sql_mkr sql_mkr, Fsm_mnt_itm mnt_itm, Object[][] rows, int owner_id_ordinal, int bin_db_id_ordinal) {
|
||||
int rows_len = rows.length;
|
||||
for (int i = 0; i < rows_len; ++i) {
|
||||
Object[] row = rows[i];
|
||||
int bin_db_id = Int_.cast_(row[bin_db_id_ordinal]); if (bin_db_id == -1) continue;
|
||||
Fsm_bin_fil bin_db = mnt_itm.Bin_mgr().Dbs__get_at(bin_db_id);
|
||||
int owner_id = Int_.cast_(row[owner_id_ordinal]);
|
||||
String sql = sql_mkr.Bin_by_id(owner_id);
|
||||
Write_sect(bfr, "fsdb.bin.select", sql);
|
||||
Object[][] bin_rows = Db_rdr_utl.Load(bin_db.Conn(), sql);
|
||||
Db_rdr_utl.Write_to_bfr(bfr, bin_rows, 4);
|
||||
Export_bins(bfr, file_bry, bin_rows, 0, 4);
|
||||
}
|
||||
}
|
||||
private void Export_bins(Bry_bfr bfr, byte[] file_bry, Object[][] rows, int owner_id_ordinal, int bin_data_ordinal) {
|
||||
int rows_len = rows.length;
|
||||
Bry_bfr tmp_bfr = Bry_bfr.new_();
|
||||
for (int i = 0; i < rows_len; ++i) {
|
||||
Object[] row = rows[i];
|
||||
int owner_id = Int_.cast_(row[owner_id_ordinal]);
|
||||
byte[] bin_data = (byte[])row[bin_data_ordinal];
|
||||
file_bry = gplx.xowa.files.repos.Xof_repo_itm_.Ttl_invalid_fsys_chars(tmp_bfr, file_bry);
|
||||
Io_url bin_url = tmp_dir.GenSubFil(String_.new_u8(file_bry));
|
||||
bin_url = tmp_dir.GenSubFil(bin_url.NameOnly() + "_" + Int_.Xto_str(owner_id) + bin_url.Ext());
|
||||
Write_kv(bfr, "fsdb.bin.export", bin_url.Raw());
|
||||
Write_kv(bfr, "fsdb.bin.len", bin_data.length);
|
||||
Io_mgr.I.SaveFilBry(bin_url, bin_data);
|
||||
}
|
||||
}
|
||||
private static void Write_kv(Bry_bfr bfr, String key, Object val) {
|
||||
bfr.Add_str_u8(key);
|
||||
bfr.Add_str_a7(" = ");
|
||||
bfr.Add_obj(val);
|
||||
bfr.Add_byte_nl();
|
||||
}
|
||||
private static void Write_sect(Bry_bfr bfr, String key, Object val) {
|
||||
bfr.Add_byte_nl();
|
||||
bfr.Add_str_u8("------------------------------------------------------").Add_byte_nl();
|
||||
bfr.Add_str_u8(key).Add_str_a7(": ").Add_obj(val).Add_byte_nl();
|
||||
bfr.Add_str_u8("------------------------------------------------------").Add_byte_nl();
|
||||
}
|
||||
private static final byte[] Arg_wiki = Bry_.new_a7("wiki"), Arg_file = Bry_.new_a7("file");
|
||||
public static final Xows_cmd__file_check I = new Xows_cmd__file_check(); Xows_cmd__file_check() {}
|
||||
}
|
||||
interface Fsdb_sql_mkr {
|
||||
String Orig_by_ttl(byte[] ttl);
|
||||
String Fil_by_ttl(byte[] ttl);
|
||||
String Thm_by_id(int id);
|
||||
String Bin_by_id(int id);
|
||||
}
|
||||
abstract class Fsdb_sql_mkr__base {
|
||||
public String Fil_by_ttl(byte[] ttl) {return String_.Format("SELECT * FROM fsdb_fil WHERE fil_name = '{0}';", ttl);}
|
||||
public String Bin_by_id(int id) {return String_.Format("SELECT * FROM fsdb_bin WHERE bin_owner_id = {0};", id);}
|
||||
}
|
||||
class Fsdb_sql_mkr__v1 extends Fsdb_sql_mkr__base implements Fsdb_sql_mkr {
|
||||
public String Orig_by_ttl(byte[] ttl) {return String_.Format("SELECT * FROM wiki_orig WHERE orig_ttl = '{0}';", ttl);}
|
||||
public String Thm_by_id(int id) {return String_.Format("SELECT * FROM fsdb_xtn_thm WHERE thm_owner_id = {0};", id);}
|
||||
public static final Fsdb_sql_mkr I = new Fsdb_sql_mkr__v1(); Fsdb_sql_mkr__v1() {}
|
||||
}
|
||||
class Fsdb_sql_mkr__v2 extends Fsdb_sql_mkr__base implements Fsdb_sql_mkr {
|
||||
public String Orig_by_ttl(byte[] ttl) {return String_.Format("SELECT * FROM orig_reg WHERE orig_ttl = '{0}';", ttl);}
|
||||
public String Thm_by_id(int id) {return String_.Format("SELECT * FROM fsdb_thm WHERE thm_owner_id = {0};", id);}
|
||||
public static final Fsdb_sql_mkr I = new Fsdb_sql_mkr__v2(); Fsdb_sql_mkr__v2() {}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.xowa.diags; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.xowa.*;
|
||||
import gplx.ios.*;
|
||||
import gplx.fsdb.meta.*;
|
||||
class Xows_cmd__fs_check {
|
||||
public void Exec(Bry_bfr bfr, Xoa_app app, Xoa_url url, Xoa_url_arg_hash arg_hash) {
|
||||
byte[] dir_bry = arg_hash.Get_val_bry_or(Arg_dir, null);
|
||||
if (dir_bry != null) {
|
||||
Write_dir(bfr, Io_url_.new_dir_(String_.new_u8(dir_bry)));
|
||||
return;
|
||||
}
|
||||
byte[] wiki_bry = arg_hash.Get_val_bry_or(Arg_wiki, null); if (wiki_bry == null) {Xoa_app_.Usr_dlg().Warn_many("", "", "special.cmd; no wiki: url=~{0}", url.Raw()); return;}
|
||||
Xow_wiki wiki = app.Wiki_mgri().Get_by_key_or_make_init_y(wiki_bry);
|
||||
Io_url wiki_dir = wiki.Fsys_mgr().Root_dir();
|
||||
Io_url file_dir = wiki.Fsys_mgr().File_dir();
|
||||
Write_dir(bfr, wiki_dir);
|
||||
Write_dir(bfr, file_dir);
|
||||
Write_dir(bfr, file_dir.GenSubDir(Fsm_mnt_tbl.Mnt_name_main));
|
||||
Write_dir(bfr, file_dir.GenSubDir(Fsm_mnt_tbl.Mnt_name_user));
|
||||
Write_dir(bfr, file_dir.GenSubDir("fsdb.update_00"));
|
||||
}
|
||||
private void Write_dir(Bry_bfr bfr, Io_url dir_url) {
|
||||
bfr.Add_byte_nl().Add_str_a7("scanning: ").Add_str_u8(dir_url.Raw()).Add_byte_nl();
|
||||
if (!Io_mgr.I.ExistsDir(dir_url)) return;
|
||||
IoItmDir dir_itm = Io_mgr.I.QueryDir_args(dir_url).Recur_(false).DirInclude_(true).ExecAsDir();
|
||||
IoItmList sub_itms = dir_itm.SubDirs(); int len = sub_itms.Count();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
try {
|
||||
IoItmDir sub_itm = (IoItmDir)sub_itms.Get_at(i);
|
||||
bfr.Add_str_a7("dir").Add_byte_pipe().Add_str_u8(sub_itm.Name()).Add_byte_nl();
|
||||
} catch (Exception e) {bfr.Add_str_u8(Err_.Message_gplx(e));}
|
||||
}
|
||||
sub_itms = dir_itm.SubFils(); len = sub_itms.Count();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
try {
|
||||
IoItmFil sub_itm = (IoItmFil)sub_itms.Get_at(i);
|
||||
bfr.Add_str_a7("fil").Add_byte_pipe().Add_str_u8(sub_itm.Name()).Add_byte_pipe().Add_long_variable(sub_itm.Size()).Add_byte_pipe().Add_dte(sub_itm.ModifiedTime()).Add_byte_nl();
|
||||
} catch (Exception e) {bfr.Add_str_u8(Err_.Message_gplx(e));}
|
||||
}
|
||||
}
|
||||
public static final Xows_cmd__fs_check I = new Xows_cmd__fs_check(); Xows_cmd__fs_check() {}
|
||||
private static final byte[] Arg_wiki = Bry_.new_a7("wiki"), Arg_dir = Bry_.new_a7("dir");
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.xowa.diags; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.xowa.*;
|
||||
import gplx.ios.*; import gplx.core.primitives.*;
|
||||
import gplx.dbs.*;
|
||||
import gplx.fsdb.meta.*;
|
||||
class Xows_cmd__sql_dump {
|
||||
public void Exec(Bry_bfr bfr, Xoa_app app, Xoa_url url, Xoa_url_arg_hash arg_hash) {
|
||||
Db_conn conn = null;
|
||||
byte[] sql_bry = arg_hash.Get_val_bry_or(Arg_sql, null); if (sql_bry == null) {Xoa_app_.Usr_dlg().Warn_many("", "", "special.cmd; no sql: url=~{0}", url.Raw()); return;}
|
||||
byte[] wiki_bry = arg_hash.Get_val_bry_or(Arg_wiki, null);
|
||||
if (wiki_bry == null) {
|
||||
byte[] db_file_bry = arg_hash.Get_val_bry_or(Arg_db_file, null); if (db_file_bry == null) {Xoa_app_.Usr_dlg().Warn_many("", "", "special.cmd; no db_type: url=~{0}", url.Raw()); return;}
|
||||
conn = Db_conn_bldr.I.Get(Io_url_.new_fil_(String_.new_u8(db_file_bry)));
|
||||
}
|
||||
else {
|
||||
byte[] db_type_bry = arg_hash.Get_val_bry_or(Arg_db_type, null); if (db_type_bry == null) {Xoa_app_.Usr_dlg().Warn_many("", "", "special.cmd; no db_type: url=~{0}", url.Raw()); return;}
|
||||
Xow_wiki wiki = app.Wiki_mgri().Get_by_key_or_make_init_y(wiki_bry);
|
||||
Byte_obj_val db_type_val = (Byte_obj_val)db_type_hash.Get_by_bry(db_type_bry); if (db_type_val == null) {Xoa_app_.Usr_dlg().Warn_many("", "", "special.cmd; bad db_type: url=~{0}", url.Raw()); return;}
|
||||
switch (db_type_val.Val()) {
|
||||
case Db_type_wiki_core: conn = wiki.Data__core_mgr().Db__core().Conn(); break;
|
||||
case Db_type_fsdb_abc: conn = wiki.File__fsdb_core().File__abc_file__at(Fsm_mnt_mgr.Mnt_idx_main).Conn(); break;
|
||||
case Db_type_fsdb_atr: conn = wiki.File__fsdb_core().File__atr_file__at(Fsm_mnt_mgr.Mnt_idx_main).Conn(); break;
|
||||
}
|
||||
}
|
||||
Db_rdr_utl.Load_and_write(conn, String_.new_u8(sql_bry), bfr);
|
||||
}
|
||||
public static final Xows_cmd__sql_dump I = new Xows_cmd__sql_dump(); Xows_cmd__sql_dump() {}
|
||||
private static final byte[] Arg_wiki = Bry_.new_a7("wiki"), Arg_db_file = Bry_.new_a7("db_file"), Arg_db_type = Bry_.new_a7("db_type"), Arg_sql = Bry_.new_a7("sql");
|
||||
private static final byte Db_type_fsdb_abc = 1, Db_type_fsdb_atr = 2, Db_type_wiki_core = 3;
|
||||
private static final Hash_adp_bry db_type_hash = Hash_adp_bry.cs_()
|
||||
.Add_str_byte("fsdb.abc" , Db_type_fsdb_abc)
|
||||
.Add_str_byte("fsdb.atr" , Db_type_fsdb_atr)
|
||||
.Add_str_byte("wiki.core" , Db_type_wiki_core)
|
||||
;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.xowa.diags; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.xowa.*;
|
||||
import gplx.core.primitives.*;
|
||||
public class Xows_diag_page implements Xows_page {
|
||||
private Xoa_url_arg_hash arg_hash = new Xoa_url_arg_hash();
|
||||
public Xows_special_meta Special_meta() {return Xows_special_meta_.Itm__diag;}
|
||||
public void Special_gen(Xowe_wiki wiki, Xoae_page page, Xoa_url url, Xoa_ttl ttl) {
|
||||
arg_hash.Load(url);
|
||||
byte[] cmd_type_bry = arg_hash.Get_val_bry_or(Arg_type, null); if (cmd_type_bry == null) {Xoa_app_.Usr_dlg().Warn_many("", "", "special.cmd; no type: url=~{0}", url.Raw()); return;}
|
||||
Byte_obj_val cmd_type_val = (Byte_obj_val)type_hash.Get_by_bry(cmd_type_bry); if (cmd_type_val == null) {Xoa_app_.Usr_dlg().Warn_many("", "", "special.cmd; bad type: url=~{0}", url.Raw()); return;}
|
||||
Bry_bfr bfr = wiki.Utl__bfr_mkr().Get_m001();
|
||||
bfr.Add_str_a7("<pre>\n");
|
||||
switch (cmd_type_val.Val()) {
|
||||
case Type_file_check: Xows_cmd__file_check.I.Exec(bfr, wiki.App(), url, arg_hash); break;
|
||||
case Type_fs_check: Xows_cmd__fs_check.I.Exec(bfr, wiki.App(), url, arg_hash); break;
|
||||
case Type_sql_dump: Xows_cmd__sql_dump.I.Exec(bfr, wiki.App(), url, arg_hash); break;
|
||||
}
|
||||
bfr.Add_str_a7("</pre>\n");
|
||||
page.Data_raw_(bfr.Xto_bry_and_clear());
|
||||
}
|
||||
private static final byte[] Arg_type = Bry_.new_a7("type");
|
||||
private static final byte Type_file_check = 1, Type_fs_check = 2, Type_sql_dump = 3;
|
||||
private static final Hash_adp_bry type_hash = Hash_adp_bry.cs_()
|
||||
.Add_str_byte("file.check" , Type_file_check)
|
||||
.Add_str_byte("fs.check" , Type_fs_check)
|
||||
.Add_str_byte("sql.dump" , Type_sql_dump)
|
||||
;
|
||||
}
|
||||
@@ -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.specials.xowa.file_browsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.xowa.*;
|
||||
import gplx.core.primitives.*;
|
||||
class Xoa_url_arg_mgr {
|
||||
private final Hash_adp_bry hash = Hash_adp_bry.cs_();
|
||||
private final Xoa_url_enum_mgr enm_mgr;
|
||||
public Xoa_url_arg_mgr(Xoa_url_enum_mgr enm_mgr) {this.enm_mgr = enm_mgr;}
|
||||
public void Init(Gfo_url_arg[] args) {
|
||||
hash.Clear();
|
||||
int len = args.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Gfo_url_arg arg = args[i];
|
||||
hash.Add_bry_obj(arg.Key_bry(), arg);
|
||||
}
|
||||
}
|
||||
public int Read_enm_or_neg1(byte[] key) {
|
||||
Xoa_url_enum_itm enm = enm_mgr.Get(key); if (enm == null) return -1;
|
||||
Gfo_url_arg arg = (Gfo_url_arg)hash.Get_by_bry(key); if (arg == null) return -1;
|
||||
return enm.Get_as_int_or(arg.Val_bry(), -1);
|
||||
}
|
||||
public byte[] Read_bry_or_empty(byte[] key) {return Read_bry_or(key, Bry_.Empty);}
|
||||
public byte[] Read_bry_or_null(byte[] key) {return Read_bry_or(key, null);}
|
||||
public byte[] Read_bry_or(byte[] key, byte[] or) {
|
||||
Gfo_url_arg arg = (Gfo_url_arg)hash.Get_by_bry(key);
|
||||
return arg == null ? or : arg.Val_bry();
|
||||
}
|
||||
public String Read_str_or_null(String key) {return Read_str_or_null(Bry_.new_u8(key));}
|
||||
public String Read_str_or_null(byte[] key) {
|
||||
Gfo_url_arg arg = (Gfo_url_arg)hash.Get_by_bry(key);
|
||||
return arg == null ? null : String_.new_u8(arg.Val_bry());
|
||||
}
|
||||
}
|
||||
class Xoa_url_enum_mgr {
|
||||
private final Hash_adp_bry hash = Hash_adp_bry.cs_();
|
||||
public Xoa_url_enum_mgr(Xoa_url_enum_itm... ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Xoa_url_enum_itm itm = ary[i];
|
||||
hash.Add_bry_obj(itm.Key(), itm);
|
||||
}
|
||||
}
|
||||
public Xoa_url_enum_itm Get(byte[] key) {return (Xoa_url_enum_itm)hash.Get_by_bry(key);}
|
||||
}
|
||||
class Xoa_url_enum_itm {
|
||||
private final Hash_adp_bry hash = Hash_adp_bry.cs_();
|
||||
public Xoa_url_enum_itm(byte[] key) {this.key = key;}
|
||||
public byte[] Key() {return key;} private final byte[] key;
|
||||
public Xoa_url_enum_itm Add(String key, int val) {
|
||||
hash.Add_bry_obj(Bry_.new_u8(key), Int_obj_val.new_(val));
|
||||
return this;
|
||||
}
|
||||
public int Get_as_int_or(byte[] val, int or) {
|
||||
Int_obj_val rv = (Int_obj_val)hash.Get_by_bry(val);
|
||||
return rv == null ? or : rv.Val();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.xowa.file_browsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.xowa.*;
|
||||
import gplx.ios.*; import gplx.xowa2.apps.*; import gplx.xowa2.wikis.*;
|
||||
interface Xosp_fbrow_cmd {
|
||||
Xosp_fbrow_cmd Make_new();
|
||||
Xosp_fbrow_rslt Write_html(Xoa_url_arg_mgr arg_mgr, GfoInvkAble select_invkable);
|
||||
}
|
||||
abstract class Xosp_fbrow_cmd__base implements Xosp_fbrow_cmd {
|
||||
public abstract Xosp_fbrow_cmd Make_new();
|
||||
public Xosp_fbrow_rslt Write_html(Xoa_url_arg_mgr arg_mgr, GfoInvkAble select_invkable) {
|
||||
// app.I18n_mgr_Get_txt_many("xowa.specials.file_browsers.errs.unknown_path", url.Raw());
|
||||
Url_encoder encoder = Url_encoder.new_html_href_mw_();
|
||||
Xosp_fbrow_html html_wtr = new Xosp_fbrow_html(encoder);
|
||||
Bry_bfr tmp_bfr = Bry_bfr.reset_(255);
|
||||
String selected_str = arg_mgr.Read_str_or_null("selected");
|
||||
if (selected_str == null) {
|
||||
String path_str = arg_mgr.Read_str_or_null("path"); if (path_str == null) return Xosp_fbrow_rslt.err_("url has unknown path");
|
||||
// if (Op_sys.Cur().Tid_is_wnt()) path_str = String_.Replace(path_str, "/", "\\");
|
||||
Io_url path_url = Io_url_.new_any_(path_str);
|
||||
IoItmDir dir = Io_mgr.I.QueryDir_args(path_url).DirInclude_(true).ExecAsDir();
|
||||
dir.SubDirs().Sort(); dir.SubFils().Sort();
|
||||
Xosp_fbrow_data_dir dir_itm = Xosp_fbrow_data_dir.new_(dir);
|
||||
Process_itms(dir_itm);
|
||||
String url_enc = String_.Replace(path_url.Raw(), "\\", "\\\\");
|
||||
byte[] cmd_src = this.Cmd_src();
|
||||
byte[] cmd_row = Html_body_cmd_row.Bld_bry_many(tmp_bfr, url_enc, cmd_src, this.Cmd_gui());
|
||||
html_wtr.Write(tmp_bfr, cmd_src, cmd_row, dir_itm);
|
||||
return new Xosp_fbrow_rslt(Html_head_default, tmp_bfr.Xto_bry_and_clear());
|
||||
}
|
||||
else
|
||||
return Write_html_selected(arg_mgr, selected_str, select_invkable);
|
||||
}
|
||||
private void Process_itms(Xosp_fbrow_data_dir dir_itm) {
|
||||
int len = dir_itm.Count();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Xosp_fbrow_data_sub itm = dir_itm.Get_at(i);
|
||||
this.Process_itm(itm);
|
||||
}
|
||||
}
|
||||
protected abstract byte[] Cmd_src();
|
||||
protected abstract String Cmd_gui();
|
||||
protected abstract Xosp_fbrow_rslt Write_html_selected(Xoa_url_arg_mgr arg_mgr, String selected, GfoInvkAble select_invkable);
|
||||
protected abstract void Process_itm(Xosp_fbrow_data_sub itm);
|
||||
private static final byte[] Html_head_default = Bry_.new_a7(String_.Concat_lines_nl_skip_last
|
||||
( " <style type='text/css'>"
|
||||
, " .fsys_tb {border: 1px solid #AAAAAA;}"
|
||||
, " .fsys_tb td {padding: 0 1em 0 1em;}"
|
||||
, " .fsys_td_size {text-align:right;}"
|
||||
, " </style>"
|
||||
, " <script type='text/javascript'>"
|
||||
, " function get_selected_chk(url_base, chk_prefix) {"
|
||||
, " var list = document.getElementsByTagName('input');"
|
||||
, " var list_len = list.length;"
|
||||
, " var selected = '';"
|
||||
, " var chk_prefix_len = chk_prefix.length;"
|
||||
, " for (var i = 0; i < list_len; ++i) {"
|
||||
, " var chk = list[i];"
|
||||
, " if (chk.id.indexOf(chk_prefix) == 0 && chk.checked == true) {"
|
||||
, " selected = selected + chk.id.substring(chk_prefix_len) + ';';"
|
||||
, " }"
|
||||
, " }"
|
||||
, " window.location.href = url_base + selected;"
|
||||
, " }"
|
||||
, " </script>"
|
||||
))
|
||||
;
|
||||
private static final Bry_fmtr Html_body_cmd_row = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( ""
|
||||
, " <tr>"
|
||||
, " <td>"
|
||||
, " <table width='100%'>"
|
||||
, " <tr>"
|
||||
, " <td align='left'><a href='javascript:get_selected_chk(\"/wiki/Special:XowaFileBrowser?cmd=~{cmd_src}&path=~{url_enc}&selected=\", \"chk_\");'>~{cmd_gui}</a>"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
, " </table>"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
), "url_enc", "cmd_src", "cmd_gui")
|
||||
;
|
||||
}
|
||||
class Xosp_fbrow_html implements Bry_fmtr_arg {
|
||||
private final Url_encoder encoder; private Xosp_fbrow_data_dir dir; private byte[] cmd_src;
|
||||
public Xosp_fbrow_html(Url_encoder encoder) {this.encoder = encoder;}
|
||||
public void Write(Bry_bfr bfr, byte[] cmd_src, byte[] cmd_row, Xosp_fbrow_data_dir dir) {
|
||||
this.dir = dir; this.cmd_src = cmd_src;
|
||||
// app.I18n_mgr_Get_txt_none("xowa.specials.file_browsers.html.hdr.name");
|
||||
// i18n.Get_txt_none("html.hdrs.name");
|
||||
fmtr_hdr.Bld_bfr_many(bfr
|
||||
, cmd_src, cmd_row
|
||||
, "name", "size", "modified"
|
||||
, dir.Url().Raw(), String_.Replace(dir.Url().Raw(), "\\", "\\\\"), encoder.Encode_str(dir.Url().OwnerDir().Raw())
|
||||
, this
|
||||
);
|
||||
}
|
||||
public void XferAry(Bry_bfr bfr, int idx) {
|
||||
int len = dir.Count();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Xosp_fbrow_data_sub itm = (Xosp_fbrow_data_sub)dir.Get_at(i);
|
||||
String selected_html = itm.Selectable() ? ("<input type='checkbox' id='chk_" + itm.Url().NameAndExt_noDirSpr() + "'/>") : " ";
|
||||
if (itm.Tid_is_dir())
|
||||
fmtr_row_dir.Bld_bfr_many(bfr, selected_html, encoder.Encode_str(itm.Url().Raw()), itm.Url().NameOnly(), cmd_src);
|
||||
else {
|
||||
fmtr_row_fil.Bld_bfr_many(bfr, selected_html, encoder.Encode_str(itm.Url().Raw()), itm.Url().NameAndExt()
|
||||
, Io_size_.To_str(itm.Size(), 1, "#,###", " ", Bool_.Y), itm.Modified().XtoStr_fmt_yyyy_MM_dd_HH_mm_ss());
|
||||
}
|
||||
}
|
||||
}
|
||||
private static Bry_fmtr
|
||||
fmtr_hdr = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( "<table>~{cmd_row}"
|
||||
, " <tr>"
|
||||
, " <td style='width:100%;border:1px solid #AAAAAA;'>~{dir_url_raw}"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
, " <tr>"
|
||||
, " <td>"
|
||||
, " <table class='sortable fsys_tb'>"
|
||||
, " <tr>"
|
||||
, " <th><!--selected--></th>"
|
||||
, " <th>~{hdr_name}</th>"
|
||||
, " <th>~{hdr_size}</th>"
|
||||
, " <th>~{hdr_modified}</th>"
|
||||
, " </tr>"
|
||||
, " <tr>"
|
||||
, " <td></td>"
|
||||
, " <td><a href='/wiki/Special:XowaFileBrowser?cmd=~{cmd_src}&path=~{owner_url_enc}'>..</a></td>"
|
||||
, " <td></td>"
|
||||
, " <td></td>"
|
||||
, " </tr>~{itms}"
|
||||
, " </table>"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
, "</table>"
|
||||
), "cmd_src", "cmd_row", "hdr_name", "hdr_size", "hdr_modified", "dir_url_raw", "dir_url_enc", "owner_url_enc", "itms"
|
||||
)
|
||||
, fmtr_row_dir = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( ""
|
||||
, " <tr>"
|
||||
, " <td>~{selected_html}</td>"
|
||||
, " <td><a href='/wiki/Special:XowaFileBrowser?cmd=~{cmd_src}&path=~{path_enc}'>~{name}</a></td>"
|
||||
, " <td></td>"
|
||||
, " <td></td>"
|
||||
, " </tr>"
|
||||
), "selected_html", "path_enc", "name", "cmd_src"
|
||||
)
|
||||
, fmtr_row_fil = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( ""
|
||||
, " <tr>"
|
||||
, " <td>~{selected_html}</td>"
|
||||
, " <td>~{name}</td>"
|
||||
, " <td class='fsys_td_size'>~{size}</td>"
|
||||
, " <td>~{modified}</td>"
|
||||
, " </tr>"
|
||||
), "selected_html", "path_enc", "name", "size", "modified"
|
||||
);
|
||||
}
|
||||
class Xosp_fbrow_cmd__err implements Xosp_fbrow_cmd {
|
||||
public Xosp_fbrow_cmd Make_new() {return this;}
|
||||
public Xosp_fbrow_rslt Write_html(Xoa_url_arg_mgr arg_mgr, GfoInvkAble select_invkable) {return Rslt;}
|
||||
private static final Xosp_fbrow_rslt Rslt = new Xosp_fbrow_rslt(Bry_.Empty, Bry_.new_u8("url has unknown cmd"));
|
||||
public static final Xosp_fbrow_cmd__err I = new Xosp_fbrow_cmd__err(); Xosp_fbrow_cmd__err() {}
|
||||
}
|
||||
class Xosp_fbrow_cmd__wiki_add extends Xosp_fbrow_cmd__base {
|
||||
@Override protected byte[] Cmd_src() {return Regy_key;}
|
||||
@Override protected String Cmd_gui() {return "import";}
|
||||
@Override public Xosp_fbrow_cmd Make_new() {return new Xosp_fbrow_cmd__wiki_add();}
|
||||
@Override protected void Process_itm(Xosp_fbrow_data_sub itm) {
|
||||
byte[] url_bry = itm.Url().RawBry();
|
||||
if (!Bry_.Has_at_end(url_bry, Ext_xowa)) itm.Selectable_(false);
|
||||
}
|
||||
@Override protected Xosp_fbrow_rslt Write_html_selected(Xoa_url_arg_mgr arg_mgr, String selected, GfoInvkAble select_invkable) {
|
||||
String[] wikis = String_.Split(selected, ";");
|
||||
String path_str = arg_mgr.Read_str_or_null("path");
|
||||
Xowv_wiki wiki = (Xowv_wiki)GfoInvkAble_.InvkCmd_val(select_invkable, Xoav_wiki_mgr.Invk_import_by_fil, path_str + wikis[0]);
|
||||
Bry_bfr bfr = Bry_bfr.reset_(255);
|
||||
done_fmtr.Bld_bfr_many(bfr, wiki.Domain_str());
|
||||
return new Xosp_fbrow_rslt(Bry_.Empty, bfr.Xto_bry_and_clear());
|
||||
}
|
||||
private static final Bry_fmtr done_fmtr = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( "<a href='/site/~{domain}/wiki/Earth'>~{domain} Main Page</a>"
|
||||
)
|
||||
, "domain");
|
||||
private static final byte[] Ext_xowa = Bry_.new_a7(".xowa");
|
||||
public static final byte[] Regy_key = Bry_.new_a7("xowa.wiki.add");
|
||||
public static final Xosp_fbrow_cmd__wiki_add I = new Xosp_fbrow_cmd__wiki_add();
|
||||
}
|
||||
class Xosp_fbrow_cmd__root_set extends Xosp_fbrow_cmd__base {
|
||||
@Override protected byte[] Cmd_src() {return Regy_key;}
|
||||
@Override protected String Cmd_gui() {return "set root dir";}
|
||||
@Override public Xosp_fbrow_cmd Make_new() {return new Xosp_fbrow_cmd__root_set();}
|
||||
@Override protected void Process_itm(Xosp_fbrow_data_sub itm) {
|
||||
if (itm.Url().Type_fil()) itm.Selectable_(false);
|
||||
}
|
||||
@Override protected Xosp_fbrow_rslt Write_html_selected(Xoa_url_arg_mgr arg_mgr, String selected, GfoInvkAble select_invkable) {
|
||||
return new Xosp_fbrow_rslt(Bry_.Empty, Bry_.new_u8(selected));
|
||||
}
|
||||
public static final byte[] Regy_key = Bry_.new_a7("xowa.fsys.root_");
|
||||
public static final Xosp_fbrow_cmd__root_set I = new Xosp_fbrow_cmd__root_set();
|
||||
}
|
||||
@@ -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.specials.xowa.file_browsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.xowa.*;
|
||||
import gplx.ios.*;
|
||||
class Xosp_fbrow_data_dir {
|
||||
private final Ordered_hash hash = Ordered_hash_.new_();
|
||||
public Xosp_fbrow_data_dir(Io_url url) {this.url = url;}
|
||||
public Io_url Url() {return url;} private final Io_url url;
|
||||
public int Count() {return hash.Count();}
|
||||
public Xosp_fbrow_data_sub Get_at(int i) {return (Xosp_fbrow_data_sub)hash.Get_at(i);}
|
||||
public void Add(Xosp_fbrow_data_sub itm) {hash.Add(itm.Url().NameAndExt(), itm);}
|
||||
public static Xosp_fbrow_data_dir new_(IoItmDir owner) {
|
||||
Xosp_fbrow_data_dir rv = new Xosp_fbrow_data_dir(owner.Url());
|
||||
new_subs(rv, Bool_.Y, owner.SubDirs());
|
||||
new_subs(rv, Bool_.N, owner.SubFils());
|
||||
return rv;
|
||||
}
|
||||
private static void new_subs(Xosp_fbrow_data_dir owner, boolean dir, IoItmList itms) {
|
||||
int len = itms.Count();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
IoItm_base src = (IoItm_base)itms.Get_at(i);
|
||||
Io_url src_url = src.Url();
|
||||
if (String_.Has_at_bgn(src_url.NameAndExt(), ".")) continue; // ignore hidden "." files; NameAndExt() b/c ".ext" has NameOnly of ""; EX: "/dir/.hidden"
|
||||
Xosp_fbrow_data_sub trg = null;
|
||||
if (dir)
|
||||
trg = new Xosp_fbrow_data_sub(src_url, -1, null);
|
||||
else {
|
||||
IoItmFil fil = (IoItmFil)src;
|
||||
trg = new Xosp_fbrow_data_sub(src_url, fil.Size(), fil.ModifiedTime());
|
||||
}
|
||||
owner.Add(trg);
|
||||
}
|
||||
}
|
||||
}
|
||||
class Xosp_fbrow_data_sub {
|
||||
public Xosp_fbrow_data_sub(Io_url url, long size, DateAdp modified) {
|
||||
this.url = url; this.size = size; this.modified = modified;
|
||||
this.tid_is_dir = url.Type_dir();
|
||||
}
|
||||
public boolean Selectable() {return selectable;} public void Selectable_(boolean v) {selectable = v;} private boolean selectable = true;
|
||||
public String Selectable_style() {return selectable ? "" : "none";}
|
||||
public boolean Tid_is_dir() {return tid_is_dir;} private final boolean tid_is_dir;
|
||||
public Io_url Url() {return url;} private final Io_url url;
|
||||
public long Size() {return size;} private final long size;
|
||||
public DateAdp Modified() {return modified;} private final DateAdp modified;
|
||||
}
|
||||
@@ -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.specials.xowa.file_browsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.xowa.*;
|
||||
public class Xosp_fbrow_rslt {
|
||||
public Xosp_fbrow_rslt(byte[] html_head, byte[] html_body) {this.html_head = html_head; this.html_body = html_body;}
|
||||
public byte[] Html_head() {return html_head;} private final byte[] html_head;
|
||||
public byte[] Html_body() {return html_body;} private final byte[] html_body;
|
||||
public static Xosp_fbrow_rslt err_(String msg) {return new Xosp_fbrow_rslt(Bry_.Empty, Bry_.new_u8(msg));}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.xowa.file_browsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.xowa.*;
|
||||
import gplx.xowa.specials.*; import gplx.ios.*;
|
||||
public class Xosp_fbrow_special implements Xows_page {
|
||||
private static final Xoa_url_arg_mgr url_args = new Xoa_url_arg_mgr(null);
|
||||
public Xows_special_meta Special_meta() {return Xows_special_meta_.Itm__file_browser;}
|
||||
public void Special_gen(Xowe_wiki wiki, Xoae_page page, Xoa_url url, Xoa_ttl ttl) {
|
||||
Xosp_fbrow_rslt rslt = Gen(url.Args(), GfoInvkAble_.Null);
|
||||
page.Html_data().Html_restricted_n_();
|
||||
page.Html_data().Custom_head_end_concat(rslt.Html_head());
|
||||
page.Data_raw_(rslt.Html_body());
|
||||
}
|
||||
public static Xosp_fbrow_rslt Gen(Gfo_url_arg[] args, GfoInvkAble select_invkable) {
|
||||
url_args.Init(args);
|
||||
byte[] cmd_bry = url_args.Read_bry_or_empty(Arg_cmd);
|
||||
Xosp_fbrow_cmd cmd = (Xosp_fbrow_cmd)cmd_regy.Get_by_bry(cmd_bry); if (cmd == null) cmd = Xosp_fbrow_cmd__err.I;
|
||||
return cmd.Make_new().Write_html(url_args, select_invkable);
|
||||
}
|
||||
private static final byte[] Arg_cmd = Bry_.new_a7("cmd");
|
||||
private static final Hash_adp_bry cmd_regy = Hash_adp_bry.cs_()
|
||||
.Add_bry_obj(Xosp_fbrow_cmd__wiki_add.Regy_key, Xosp_fbrow_cmd__wiki_add.I)
|
||||
.Add_bry_obj(Xosp_fbrow_cmd__root_set.Regy_key, Xosp_fbrow_cmd__root_set.I)
|
||||
;
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.xowa.file_browsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.xowa.*;
|
||||
import org.junit.*; import gplx.ios.*;
|
||||
public class Xosp_fbrow_special_tst {
|
||||
@Before public void init() {fxt.Clear();} private Xosp_fbrow_special_fxt fxt = new Xosp_fbrow_special_fxt();
|
||||
@Test public void Basic() {
|
||||
fxt.Init_dir(fxt.Make_dir());
|
||||
fxt.Test_nav("mem/root/dir/", String_.Concat_lines_nl_skip_last
|
||||
( "<table>"
|
||||
, " <tr>"
|
||||
, " <td>"
|
||||
, " <table width='100%'>"
|
||||
, " <tr>"
|
||||
, " <td align='left'><a href='javascript:get_selected_chk(\"/wiki/Special:XowaFileBrowser?cmd=xowa.wiki.add&path=mem/root/dir/&selected=\", \"chk_\");'>import</a>"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
, " </table>"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
, " <tr>"
|
||||
, " <td style='width:100%;border:1px solid #AAAAAA;'>mem/root/dir/"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
, " <tr>"
|
||||
, " <td>"
|
||||
, " <table class='sortable fsys_tb'>"
|
||||
, " <tr>"
|
||||
, " <th><!--selected--></th>"
|
||||
, " <th>name</th>"
|
||||
, " <th>size</th>"
|
||||
, " <th>modified</th>"
|
||||
, " </tr>"
|
||||
, " <tr>"
|
||||
, " <td></td>"
|
||||
, " <td><a href='/wiki/Special:XowaFileBrowser?cmd=xowa.wiki.add&path=mem/root/'>..</a></td>"
|
||||
, " <td></td>"
|
||||
, " <td></td>"
|
||||
, " </tr>"
|
||||
, " <tr>"
|
||||
, " <td> </td>"
|
||||
, " <td><a href='/wiki/Special:XowaFileBrowser?cmd=xowa.wiki.add&path=mem/root/dir/a/'>a</a></td>"
|
||||
, " <td></td>"
|
||||
, " <td></td>"
|
||||
, " </tr>"
|
||||
, " <tr>"
|
||||
, " <td> </td>"
|
||||
, " <td><a href='/wiki/Special:XowaFileBrowser?cmd=xowa.wiki.add&path=mem/root/dir/b/'>b</a></td>"
|
||||
, " <td></td>"
|
||||
, " <td></td>"
|
||||
, " </tr>"
|
||||
, " <tr>"
|
||||
, " <td> </td>"
|
||||
, " <td>1.txt</td>"
|
||||
, " <td class='fsys_td_size'>1 KB</td>"
|
||||
, " <td>2001-01-01 00:00:00</td>"
|
||||
, " </tr>"
|
||||
, " <tr>"
|
||||
, " <td> </td>"
|
||||
, " <td>2.txt</td>"
|
||||
, " <td class='fsys_td_size'>1 KB</td>"
|
||||
, " <td>2004-01-02 00:00:00</td>"
|
||||
, " </tr>"
|
||||
, " <tr>"
|
||||
, " <td><input type='checkbox' id='chk_3.xowa'/></td>"
|
||||
, " <td>3.xowa</td>"
|
||||
, " <td class='fsys_td_size'>1 KB</td>"
|
||||
, " <td>2004-01-03 00:00:00</td>"
|
||||
, " </tr>"
|
||||
, " </table>"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
, "</table>"
|
||||
));
|
||||
}
|
||||
}
|
||||
class Io_itm_bldr {
|
||||
public IoItmDir Root(Io_url url, IoItm_base... subs) {
|
||||
IoItmDir rv = IoItmDir_.top_(url);
|
||||
Init_dir(rv, url.NameAndExt(), subs);
|
||||
return rv;
|
||||
}
|
||||
public IoItmDir Dir(String name, IoItm_base... subs) {
|
||||
IoItmDir rv = IoItmDir_.sub_(name);
|
||||
Init_dir(rv, name, subs);
|
||||
return rv;
|
||||
}
|
||||
public IoItmFil Fil(String name, int size, String date) {return IoItmFil_.sub_(name, size, DateAdp_.parse_iso8561(date));}
|
||||
private void Init_dir(IoItmDir rv, String name, IoItm_base... subs) {
|
||||
int len = subs.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
IoItm_base sub = subs[i];
|
||||
IoItmList sub_list = sub.Type_fil() ? rv.SubFils() : rv.SubDirs();
|
||||
sub.OwnerDir_set(rv);
|
||||
sub_list.Add(sub);
|
||||
}
|
||||
}
|
||||
}
|
||||
class Xosp_fbrow_special_fxt {
|
||||
private Io_itm_bldr bldr = new Io_itm_bldr();
|
||||
public void Clear() {}
|
||||
public IoItmDir Make_dir() {
|
||||
return bldr.Root(Io_url_.mem_dir_("mem/root/dir/")
|
||||
, bldr.Dir("a"
|
||||
, bldr.Fil("a1.txt", 11, "2011-01-01")
|
||||
, bldr.Fil("a2.txt", 12, "2011-01-02")
|
||||
, bldr.Fil("a3.txt", 13, "2011-01-03")
|
||||
)
|
||||
, bldr.Dir("b"
|
||||
, bldr.Fil("b1.txt", 21, "2011-02-01")
|
||||
, bldr.Fil("b2.txt", 22, "2011-02-02")
|
||||
, bldr.Fil("b3.txt", 23, "2011-02-03")
|
||||
)
|
||||
, bldr.Fil("1.txt", 1, "2001-01-01")
|
||||
, bldr.Fil("2.txt", 2, "2004-01-02")
|
||||
, bldr.Fil("3.xowa", 3, "2004-01-03")
|
||||
);
|
||||
}
|
||||
public void Init_dir(IoItmDir dir) {
|
||||
IoItmDir_.Make(dir);
|
||||
}
|
||||
public void Test_nav(String path, String expd) {
|
||||
Xoa_url_arg_mgr args_mgr = new Xoa_url_arg_mgr(null);
|
||||
Xoa_url url = Xoa_url.new_(Bry_.Empty, Bry_.Empty).Args_(Gfo_url_arg.Ary("cmd", "xowa.wiki.add", "mode", "view", "path", path));
|
||||
args_mgr.Init(url.Args());
|
||||
Xosp_fbrow_cmd__wiki_add cmd = new Xosp_fbrow_cmd__wiki_add();
|
||||
byte[] actl = cmd.Write_html(args_mgr, GfoInvkAble_.Null).Html_body();
|
||||
Tfds.Eq_str_lines(expd, String_.new_u8(actl));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.xowa.popup_history; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.xowa.*;
|
||||
import gplx.xowa.html.modules.popups.*;
|
||||
public class Popup_history_page implements Xows_page {
|
||||
public Xows_special_meta Special_meta() {return Xows_special_meta_.Itm__popup_history;}
|
||||
public void Special_gen(Xowe_wiki wiki, Xoae_page page, Xoa_url url, Xoa_ttl ttl) {
|
||||
Xoae_page cur_page = wiki.Appe().Gui_mgr().Browser_win().Active_page(); if (cur_page == null) return;
|
||||
Ordered_hash hash = cur_page.Popup_mgr().Itms();
|
||||
int len = hash.Count();
|
||||
Bry_bfr bfr = wiki.Utl__bfr_mkr().Get_k004();
|
||||
for (int i = len - 1; i > -1; --i) {
|
||||
Xow_popup_itm itm = (Xow_popup_itm)hash.Get_at(i);
|
||||
if (Ttl_chk(itm.Page_ttl())) continue;
|
||||
fmtr_main.Bld_bfr_many(bfr, itm.Page_href(), itm.Page_ttl().Full_txt());
|
||||
}
|
||||
page.Data_raw_(bfr.Trim_end(Byte_ascii.Nl).To_bry_and_rls());
|
||||
page.Html_data().Html_restricted_n_();
|
||||
}
|
||||
private Bry_fmtr fmtr_main = Bry_fmtr.new_("<a href='~{href}'>~{ttl}</a>\n\n", "href", "ttl"); // NOTE: need to use anchor (as opposed to lnki or lnke) b/c xwiki will not work on all wikis
|
||||
public static boolean Ttl_chk(Xoa_ttl ttl) {
|
||||
return ttl.Ns().Id_special()
|
||||
&& Bry_.Eq(ttl.Page_db(), Xows_special_meta_.Itm__popup_history.Key_bry());
|
||||
}
|
||||
}
|
||||
@@ -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.specials.xowa.system_data; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.xowa.*;
|
||||
import gplx.core.primitives.*;
|
||||
public class System_data_page implements Xows_page {
|
||||
private Xoa_url_arg_hash arg_hash = new Xoa_url_arg_hash();
|
||||
public Xows_special_meta Special_meta() {return Xows_special_meta_.Itm__system_data;}
|
||||
public void Special_gen(Xowe_wiki wiki, Xoae_page page, Xoa_url url, Xoa_ttl ttl) {
|
||||
arg_hash.Load(url);
|
||||
byte[] file_type = arg_hash.Get_val_bry_or(Arg_type, null); if (file_type == null) return;
|
||||
Byte_obj_val type_val = (Byte_obj_val)type_hash.Get_by_bry(file_type); if (type_val == null) return;
|
||||
Io_url file_url = Path_from_type(wiki, type_val.Val()); if (file_url == null) return;
|
||||
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_m001();
|
||||
byte[] file_txt = Io_mgr.I.LoadFilBry(file_url);
|
||||
file_txt = gplx.html.Html_utl.Escape_html_as_bry(file_txt, true, false, false, false, false); // escape < or "</pre>" in messages will cause pre to break
|
||||
fmtr_all.Bld_bfr_many(tmp_bfr, file_url.Raw(), file_txt);
|
||||
page.Data_raw_(tmp_bfr.To_bry_and_rls());
|
||||
}
|
||||
private static Io_url Path_from_type(Xowe_wiki wiki, byte type) {
|
||||
Xoae_app app = wiki.Appe();
|
||||
switch (type) {
|
||||
case Type_log_session: return app.Log_wtr().Session_fil();
|
||||
case Type_cfg_app: return app.Fsys_mgr().Root_dir().GenSubFil("xowa.gfs");
|
||||
case Type_cfg_lang: return Xol_lang_.xo_lang_fil_(app.Fsys_mgr(), wiki.Lang().Key_str());
|
||||
case Type_cfg_user: return app.Usere().Fsys_mgr().App_data_cfg_user_fil();
|
||||
case Type_cfg_custom: return app.Usere().Fsys_mgr().App_data_cfg_custom_fil();
|
||||
case Type_usr_history: return app.Usere().Fsys_mgr().App_data_history_fil();
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static final byte[] Arg_type = Bry_.new_a7("type");
|
||||
private static final byte Type_log_session = 1, Type_cfg_app = 2, Type_cfg_lang = 3, Type_cfg_user = 4, Type_cfg_custom = 5, Type_usr_history = 6;
|
||||
private static final Hash_adp_bry type_hash = Hash_adp_bry.cs_()
|
||||
.Add_str_byte("log_session" , Type_log_session)
|
||||
.Add_str_byte("cfg_app" , Type_cfg_app)
|
||||
.Add_str_byte("cfg_lang" , Type_cfg_lang)
|
||||
.Add_str_byte("cfg_user" , Type_cfg_user)
|
||||
.Add_str_byte("cfg_custom" , Type_cfg_custom)
|
||||
.Add_str_byte("usr_history" , Type_usr_history)
|
||||
;
|
||||
private Bry_fmtr fmtr_all = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( "<p><b>Path</b>: <code>~{path}</code>"
|
||||
, "</p>"
|
||||
, "<pre style='overflow:auto;'>"
|
||||
, "~{text}</pre>"
|
||||
), "path", "text");
|
||||
}
|
||||
Reference in New Issue
Block a user