v3.3.4 v3.9.2.1
gnosygnu 8 years ago
parent 232838c732
commit 35d78f6106

@ -79,6 +79,7 @@ public class Bry_fmt {
public static Bry_fmt New(byte[] fmt, String... keys) {return new Bry_fmt(fmt , Bry_.Ary(keys), Bfr_fmt_arg.Ary_empty);}
public static String Make_str(String fmt_str, Object... vals) {return Auto(fmt_str).Vals_(vals).To_str();}
public static Bry_fmt Auto_nl_apos(String... lines) {return Auto(Bry_.New_u8_nl_apos(lines));}
public static Bry_fmt Auto_nl_skip_last(String... lines) {return Auto(Bry_.new_u8(String_.Concat_lines_nl_skip_last(lines)));}
public static Bry_fmt Auto(String fmt_str) {return Auto(Bry_.new_u8(fmt_str));}
public static Bry_fmt Auto(byte[] fmt_bry) {
byte[][] keys_bry = Bry_fmt_parser_.Parse_keys(fmt_bry);

@ -64,6 +64,8 @@ public class Io_mgr implements Gfo_evt_mgr_owner { // exists primarily to gather
public void DeleteDirDeep(Io_url url) {IoEngine_xrg_deleteDir.new_(url).Recur_().Exec();}
public void DeleteDirDeep_ary(Io_url... urls) {for (Io_url url : urls) IoEngine_xrg_deleteDir.new_(url).Recur_().Exec();}
public int Delete_dir_empty(Io_url url) {return Io_mgr_.Delete_dir_empty(url);}
public void Delete_sub_by_wildcard() {
}
public boolean Truncate_fil(Io_url url, long size) {return IoEnginePool.Instance.Get_by(url.Info().EngineKey()).Truncate_fil(url, size);}
public void MoveDirDeep(Io_url src, Io_url trg) {IoEngine_xrg_xferDir.move_(src, trg).Recur_().Exec();}
public IoEngine_xrg_xferDir CopyDir_cmd(Io_url src, Io_url trg) {return IoEngine_xrg_xferDir.copy_(src, trg);}

@ -19,15 +19,10 @@ package gplx;
import gplx.core.strings.*;
public class Time_span implements CompareAble { // NOTE: gplx.Time_span b/c System.TimeSpan
public long Fracs() {return fracs;} long fracs; public int FracsAsInt() {return (int)fracs;}
public Decimal_adp TotalSecs() {
return Decimal_adp_.divide_(fracs, Time_span_.Divisors[Time_span_.Idx_Sec]);
}
public Decimal_adp Total_days() {
return Decimal_adp_.divide_(fracs, Time_span_.Divisors[Time_span_.Idx_Hour] * 24);
}
public Decimal_adp Total_hours() {
return Decimal_adp_.divide_(fracs, Time_span_.Divisors[Time_span_.Idx_Hour]);
}
public Decimal_adp Total_days() {return Decimal_adp_.divide_(fracs, Time_span_.Divisors[Time_span_.Idx_Hour] * 24);}
public Decimal_adp Total_hours() {return Decimal_adp_.divide_(fracs, Time_span_.Divisors[Time_span_.Idx_Hour]);}
public Decimal_adp Total_mins() {return Decimal_adp_.divide_(fracs, Time_span_.Divisors[Time_span_.Idx_Min]);}
public Decimal_adp Total_secs() {return Decimal_adp_.divide_(fracs, Time_span_.Divisors[Time_span_.Idx_Sec]);}
public int[] Units() {return Time_span_.Split_long(fracs, Time_span_.Divisors);}
public int Units_fracs() {
int[] ary = Time_span_.Split_long(fracs, Time_span_.Divisors);

@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.core.ios; import gplx.*; import gplx.core.*;
import gplx.langs.gfs.*;
public class IoItmFil extends IoItm_base {
@Override public int TypeId() {return IoItmFil.Type_Fil;} @Override public boolean Type_dir() {return false;} @Override public boolean Type_fil() {return true;} public static final int Type_Fil = 2;
@Override public int TypeId() {return IoItmFil.Type_Fil;} @Override public boolean Type_dir() {return false;} @Override public boolean Type_fil() {return true;} public static final int Type_Fil = 2;
public boolean Exists() {return size != Size_invalid;} // NOTE: questionable logic, but preserved for historical reasons; requires that length be set to -1 if !.exists
public DateAdp ModifiedTime() {return modifiedTime;}
public IoItmFil ModifiedTime_(DateAdp val) {modifiedTime = val; return this;} DateAdp modifiedTime;

@ -22,4 +22,5 @@ public interface Gfo_prog_ui extends Cancelable {
long Prog_data_cur();
long Prog_data_end();
boolean Prog_notify_and_chk_if_suspended(long cur, long max);
void Prog_notify_by_msg(String msg);
}

@ -35,6 +35,7 @@ class Gfo_prog_ui__noop implements Gfo_prog_ui {
public long Prog_data_cur() {return 0;}
public long Prog_data_end() {return 0;}
public boolean Prog_notify_and_chk_if_suspended(long cur, long max) {return false;}
public void Prog_notify_by_msg(String msg) {}
}
class Gfo_prog_ui__always implements Gfo_prog_ui {
public boolean Canceled() {return false;}
@ -44,4 +45,5 @@ class Gfo_prog_ui__always implements Gfo_prog_ui {
public long Prog_data_cur() {return 0;}
public long Prog_data_end() {return 0;}
public boolean Prog_notify_and_chk_if_suspended(long cur, long max) {return false;}
public void Prog_notify_by_msg(String msg) {}
}

@ -25,7 +25,7 @@ public class Time_span__basic_tst {
}
@Test public void TotalSecs() {
Time_span val = Time_span_.fracs_(1987);
Tfds.Eq_decimal(Decimal_adp_.parts_(1, 987), val.TotalSecs());
Tfds.Eq_decimal(Decimal_adp_.parts_(1, 987), val.Total_secs());
}
@Test public void Units() {
tst_Units("01:02:03.987", 1, 2, 3, 987);

@ -21,7 +21,7 @@ public class TimeSpanAdpClassXtn extends ClassXtn_base implements ClassXtn {
@Override public Class<?> UnderClass() {return Time_span.class;}
public Object DefaultValue() {return Time_span_.Zero;}
@Override public Object ParseOrNull(String raw) {return Time_span_.parse(raw);}
@Override public Object XtoDb(Object obj) {return Time_span_.cast(obj).TotalSecs();}
@Override public Object XtoDb(Object obj) {return Time_span_.cast(obj).Total_secs();}
@Override public String XtoUi(Object obj, String fmt) {return Time_span_.cast(obj).To_str(fmt);}
public boolean Eq(Object lhs, Object rhs) {try {return Time_span_.cast(lhs).Eq(rhs);} catch (Exception e) {Err_.Noop(e); return false;}}
public static final TimeSpanAdpClassXtn Instance = new TimeSpanAdpClassXtn(); TimeSpanAdpClassXtn() {} // added to ClassXtnPool by default

@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.dbs; import gplx.*;
import gplx.dbs.qrys.*;
public class Db_stmt_ {
public static final Db_stmt Null = new Db_stmt_sql();
public static final Db_stmt Null = new Db_stmt_sql();
public static Db_stmt new_insert_(Db_conn conn, String tbl, String... flds) {
Db_qry qry = Db_qry_insert.new_(tbl, flds);
return conn.Stmt_new(qry);

@ -127,4 +127,13 @@ public abstract class Db_engine_sql_base implements Db_engine {
try {return DriverManager.getConnection(url, uid, pwd);}
catch (SQLException e) {throw Err_.new_exc(e, "db", "connection open failed", "info", Conn_info().Raw());}
}
protected Connection Conn__new_by_url_and_props(String url, Keyval... props) {
try {
java.util.Properties properties = new java.util.Properties();
for (Keyval prop : props)
properties.setProperty(prop.Key(), prop.Val_to_str_or_empty());
return DriverManager.getConnection(url, properties);
}
catch (SQLException e) {throw Err_.new_exc(e, "db", "connection open failed", "info", Conn_info().Raw());}
}
}

@ -19,6 +19,7 @@ package gplx.dbs.engines.sqlite; import gplx.*; import gplx.dbs.*; import gplx.d
import java.sql.*;
import gplx.core.stores.*; import gplx.dbs.engines.*; import gplx.dbs.engines.sqlite.*; import gplx.dbs.metas.*; import gplx.dbs.sqls.*;
import gplx.dbs.qrys.*;
import gplx.core.ios.IoItmFil;
import org.sqlite.SQLiteConnection;
public class Sqlite_engine extends Db_engine_sql_base {
private final Sqlite_txn_mgr txn_mgr; private final Sqlite_schema_mgr schema_mgr;
@ -61,8 +62,22 @@ public class Sqlite_engine extends Db_engine_sql_base {
catch (ClassNotFoundException e) {throw Err_.new_exc(e, "db", "could not load sqlite jdbc driver");}
loaded = true;
}
// init vars for opening connection
Sqlite_conn_info conn_info_as_sqlite = (Sqlite_conn_info)conn_info;
Connection rv = Conn_make_by_url("jdbc:sqlite://" + String_.Replace(conn_info_as_sqlite.Url().Raw(), "\\", "/"), "", "");
Io_url sqlite_fs_url = conn_info_as_sqlite.Url();
String sqlite_db_url = "jdbc:sqlite://" + String_.Replace(sqlite_fs_url.Raw(), "\\", "/");
// set open_mode flag if conn is read-only; needed else all SELECT queries will be very slow; DATE:2016-09-03
IoItmFil sqlite_fs_itm = Io_mgr.Instance.QueryFil(sqlite_fs_url);
Keyval[] props = sqlite_fs_itm.Exists() && sqlite_fs_itm.ReadOnly() // NOTE: must check if it exists; else missing-file will be marked as readonly connection, and missing-file will sometimes be dynamically created as read-write; DATE:2016-09-04
? Keyval_.Ary(Keyval_.new_("open_mode", "1"))
: Keyval_.Ary_empty;
// open connection
Connection rv = Conn__new_by_url_and_props(sqlite_db_url, props);
// set busyTimeout; needed else multiple processes accessing same db can cause "database is locked" error; DATE:2016-09-03
SQLiteConnection rv_as_sqlite = (org.sqlite.SQLiteConnection)rv;
try {rv_as_sqlite.setBusyTimeout(10000);}
catch (SQLException e) {Gfo_usr_dlg_.Instance.Warn_many("", "", "failed to set busy timeout; err=~{0}", Err_.Message_gplx_log(e));}

@ -36,7 +36,7 @@ public class Db_stmt_arg_list {
}
list.Clear();
}
private static void Fill_crt(Db_stmt stmt, int tid, String key, Object val) {
public static void Fill_crt(Db_stmt stmt, int tid, String key, Object val) {
switch (tid) {
case Dbmeta_fld_tid.Tid__bool: stmt.Crt_bool_as_byte (key, Bool_.cast(val)); break;
case Dbmeta_fld_tid.Tid__byte: stmt.Crt_byte (key, Byte_.cast(val)); break;

@ -0,0 +1,80 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.dbs.utls; import gplx.*; import gplx.dbs.*;
import gplx.dbs.stmts.*;
public class Db_tbl__crud_ {
public static void Upsert(Db_conn conn, String tbl_name, Dbmeta_fld_list flds, String[] crt_cols, Object... objs) {
// init
int crt_cols_len = crt_cols.length;
String[] val_cols = Find_excepts(flds, crt_cols);
// check if exists
Db_stmt select_stmt = conn.Stmt_select(tbl_name, crt_cols, crt_cols);
Add_arg(select_stmt, flds, crt_cols, objs, Bool_.Y, 0);
Db_rdr rdr = select_stmt.Exec_select__rls_auto();
boolean exists = rdr.Move_next();
rdr.Rls();
// do update / insert; NOTE: 0-index and crt_cols_len assumes that objs starts with crts; EX: (id) -> (1, 'abc') x> ('abc', 1)
// update
if (exists) {
Db_stmt update_stmt = conn.Stmt_update(tbl_name, crt_cols, crt_cols);
Add_arg(update_stmt, flds, crt_cols, objs, Bool_.Y, 0);
Add_arg(update_stmt, flds, val_cols, objs, Bool_.N, crt_cols_len);
update_stmt.Exec_update();
update_stmt.Rls();
}
// insert
else {
Db_stmt insert_stmt = conn.Stmt_insert(tbl_name, flds);
Add_arg(insert_stmt, flds, crt_cols, objs, Bool_.N, 0);
Add_arg(insert_stmt, flds, val_cols, objs, Bool_.N, crt_cols_len);
insert_stmt.Exec_insert();
insert_stmt.Rls();
}
}
private static String[] Find_excepts(Dbmeta_fld_list flds, String[] cols) {
// hash cols
Hash_adp hash = Hash_adp_.New();
int cols_len = cols.length;
for (int i = 0; i < cols_len; ++i)
hash.Add_as_key_and_val(cols[i]);
// loop flds and get excepts
List_adp list = List_adp_.New();
int flds_len = flds.Len();
for (int i = 0; i < flds_len; ++i) {
Dbmeta_fld_itm fld = flds.Get_at(i);
if (!hash.Has(fld.Name()))
list.Add(fld.Name());
}
return list.To_str_ary_and_clear();
}
private static void Add_arg(Db_stmt stmt, Dbmeta_fld_list flds, String[] cols, Object[] objs, boolean mode_is_crt, int objs_bgn) {
int cols_len = cols.length;
for (int i = 0; i < cols_len; ++i) {
String col = cols[i];
Dbmeta_fld_itm fld = flds.Get_by(col);
Object obj = objs[i + objs_bgn];
if (mode_is_crt)
Db_stmt_arg_list.Fill_crt(stmt, fld.Type().Tid_ansi(), col, obj);
else
Db_stmt_arg_list.Fill_val(stmt, fld.Type().Tid_ansi(), col, obj);
}
}
}

@ -21,6 +21,7 @@ public class Hash_adp__int {
private final Hash_adp hash = Hash_adp_.New();
private final Int_obj_ref tmp_key = Int_obj_ref.New_neg1();
public void Clear() {hash.Clear();}
public int Len() {return hash.Count();}
public Object Get_by(int key) {return hash.Get_by_or_fail(tmp_key.Val_(key));}
public Object Get_by_or_null(int key) {return hash.Get_by(tmp_key.Val_(key));}
public void Add(int key, Object obj) {hash.Add(Int_obj_ref.New(key), obj);}

@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.core.net.downloads; import gplx.*; import gplx.core.*; import gplx.core.net.*;
public interface Http_download_wkr {
String Fail_msg();
Io_url Tmp_url();
Http_download_wkr Make_new();
long Checkpoint__load_by_trg_fil(Io_url trg_url);
byte Exec(gplx.core.progs.Gfo_prog_ui prog_ui, String src_str, Io_url trg_url, long expd_size);

@ -22,6 +22,7 @@ public abstract class Http_download_wkr__base implements Http_download_wkr {
private Io_url tmp_url, checkpoint_url;
private long downloaded;
private long checkpoint_interval = 1024 * 1024, checkpoint_nxt = 0;
public Io_url Tmp_url() {return tmp_url;}
public String Fail_msg() {return fail_msg;} private String fail_msg;
public abstract Http_download_wkr Make_new();
public byte Exec(gplx.core.progs.Gfo_prog_ui prog_ui, String src_str, Io_url trg_url, long expd_size_val) {
@ -30,7 +31,12 @@ public abstract class Http_download_wkr__base implements Http_download_wkr {
this.expd_size = expd_size_val;
this.fail_msg = null;
byte status = this.Exec_hook(prog_ui, src_str, tmp_url, downloaded);
byte status = Gfo_prog_ui_.Status__fail;
try {status = this.Exec_hook(prog_ui, src_str, tmp_url, downloaded);}
catch (Exception e) {
status = Gfo_prog_ui_.Status__fail;
fail_msg = Err_.Message_lang(e);
}
switch (status) {
case Gfo_prog_ui_.Status__done: {
if (expd_size_val != -1) {

@ -39,7 +39,7 @@ public class Http_download_wkr__jre extends Http_download_wkr__base {
URL src_url_itm = null;
try {src_url_itm = new URL(src_url);}
catch (MalformedURLException e) {
try {trg_stream.close();}
try {if (trg_stream != null) trg_stream.close();}
catch (IOException e1) {}
throw Err_.new_("download_file", "bad url", "src", src_url, "err" + e.toString());
}
@ -49,26 +49,29 @@ public class Http_download_wkr__jre extends Http_download_wkr__base {
src_conn = (HttpURLConnection)src_url_itm.openConnection();
if (prog_resumed)
src_conn.addRequestProperty("Range", "bytes=" + Long_.To_str(prog_data_cur) + "-");
src_conn.setReadTimeout(10000); // explicitly set timeout; NOTE:needed on Mac OS X, else error never thrown; DATE:2016-09-03
src_conn.connect();
// check response code
int response_code = src_conn.getResponseCode();
if (prog_resumed) {
if (response_code != HttpURLConnection.HTTP_PARTIAL) {
try {trg_stream.close();}
try {if (trg_stream != null) trg_stream.close();}
catch (IOException e1) {}
throw Err_.new_("download_file", "server returned non-partial response code", "src", src_url, "code", src_conn.getResponseCode(), "msg", src_conn.getResponseMessage());
}
}
else {
if (response_code != HttpURLConnection.HTTP_OK) {
try {trg_stream.close();}
try {if (trg_stream != null) trg_stream.close();}
catch (IOException e1) {}
throw Err_.new_("download_file", "server returned non-OK response code", "src", src_url, "code", src_conn.getResponseCode(), "msg", src_conn.getResponseMessage());
}
}
src_stream = src_conn.getInputStream();
} catch (Exception e) {
try {if (trg_stream != null) trg_stream.close();}
catch (IOException e1) {}
throw Err_.new_("download_file", "src connection failed", "src", src_url, "err",e.toString());
}
@ -77,8 +80,9 @@ public class Http_download_wkr__jre extends Http_download_wkr__base {
long prog_data_end = prog_ui.Prog_data_end();
if (prog_data_end == -1) prog_data_end = src_conn.getContentLength(); // NOTE: may be -1 if server does not report the length
byte data[] = new byte[4096];
int read = 0;
while ((read = src_stream.read(data)) != -1) {
while (true) {
int read = src_stream.read(data);
if (read == -1) break; // no more data
prog_data_cur += read;
trg_stream.write(data, 0, read);
this.Checkpoint__save(prog_data_cur);

@ -301,7 +301,7 @@ public class Gfh_tag_rdr {
}
Gfh_tag tmp = move ? tag__tmp__move : tag__tmp__peek;
return tmp.Init(this, src, cur_is_tail, inline, tag_bgn, tag_end, name_end, atrs_end
, name_hash.Get_as_int_or(src, name_bgn, name_end, -1) // TODO: change from -1 to Unknown
, name_hash.Get_as_int_or(src, name_bgn, name_end, -1) // TODO_OLD: change from -1 to Unknown
, Bry_.Mid(src, name_bgn, name_end));
}
public boolean Read_and_move(byte match) {

@ -32,7 +32,7 @@ public class Xoa_app_ {
}
}
public static final String Name = "xowa";
public static final String Version = "3.8.5.1";
public static final String Version = "3.9.2.1";
public static String Build_date = "2012-12-30 00:00:00";
public static String Op_sys_str;
public static String User_agent = "";

@ -16,7 +16,8 @@ You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa; import gplx.*;
import gplx.xowa.wikis.pages.*; import gplx.xowa.wikis.pages.lnkis.*; import gplx.xowa.wikis.pages.dbs.*; import gplx.xowa.wikis.pages.redirects.*; import gplx.xowa.wikis.pages.hdumps.*; import gplx.xowa.wikis.pages.htmls.*;
import gplx.xowa.langs.*;
import gplx.xowa.wikis.pages.*; import gplx.xowa.wikis.pages.lnkis.*; import gplx.xowa.wikis.pages.dbs.*; import gplx.xowa.wikis.pages.redirects.*; import gplx.xowa.wikis.pages.hdumps.*; import gplx.xowa.wikis.pages.htmls.*; import gplx.xowa.wikis.pages.wtxts.*;
public interface Xoa_page {
Xow_wiki Wiki();
Xoa_url Url(); byte[] Url_bry_safe();
@ -25,6 +26,8 @@ public interface Xoa_page {
Xopg_redirect_mgr Redirect_trail();
Xopg_html_data Html_data();
Xopg_hdump_data Hdump_mgr();
Xopg_wtxt_data Wtxt();
Xol_lang_itm Lang();
Xoa_page__commons_mgr Commons_mgr();
boolean Xtn__timeline_exists();

@ -19,7 +19,13 @@ package gplx.xowa; import gplx.*;
public class Xoa_page_ {
public static final byte Edit_mode_create = 1, Edit_mode_update = 2;
public static final String Main_page_str = "Main_Page";
public static final byte[] Main_page_bry = Bry_.new_a7(Main_page_str); // NOTE; may not work for non-english wikis
public static final byte[] Main_page_bry_empty = Bry_.Empty;
public static final byte[] Main_page_bry = Bry_.new_a7(Main_page_str); // NOTE; may not work for non-english wikis
public static final byte[] Main_page_bry_empty = Bry_.Empty;
public static final int Page_len_max = 2048 * Io_mgr.Len_kb; // REF.MW: DefaultSettings.php; $wgMaxArticleSize = 2048;
public static byte[] Url_bry_safe(Xoa_url url, Xow_wiki wiki, Xoa_ttl ttl) {
byte[] rv = url == null ? Bry_.Empty : url.To_bry(Bool_.Y, Bool_.Y);
if (Bry_.Len_eq_0(rv))
rv = Bry_.Add(wiki == null ? Bry_.Empty : wiki.Domain_bry(), gplx.xowa.htmls.hrefs.Xoh_href_.Bry__wiki, ttl == null ? Bry_.Empty : ttl.Full_db());
return rv;
}
}

@ -22,7 +22,7 @@ import gplx.xowa.langs.*; import gplx.xowa.specials.*; import gplx.xowa.apps.cfg
import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.css.*; import gplx.xowa.bldrs.installs.*;
import gplx.xowa.files.*; import gplx.xowa.files.caches.*; import gplx.xowa.files.imgs.*;
import gplx.xowa.guis.cbks.*; import gplx.xowa.guis.tabs.*;
import gplx.xowa.wikis.*; import gplx.xowa.users.*; import gplx.xowa.guis.*; import gplx.xowa.apps.cfgs.*; import gplx.xowa.wikis.ctgs.*; import gplx.xowa.addons.htmls.tocs.*; import gplx.xowa.apps.fmtrs.*; import gplx.xowa.htmls.*; import gplx.xowa.wikis.xwikis.sitelinks.*; import gplx.xowa.wikis.xwikis.parsers.*;
import gplx.xowa.wikis.*; import gplx.xowa.users.*; import gplx.xowa.guis.*; import gplx.xowa.apps.cfgs.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.htmls.tocs.*; import gplx.xowa.apps.fmtrs.*; import gplx.xowa.htmls.*; import gplx.xowa.wikis.xwikis.sitelinks.*; import gplx.xowa.wikis.xwikis.parsers.*;
import gplx.xowa.htmls.hrefs.*; import gplx.xowa.htmls.core.htmls.utls.*; import gplx.xowa.htmls.ns_files.*; import gplx.xowa.htmls.bridges.*;
import gplx.xowa.parsers.*; import gplx.xowa.parsers.amps.*; import gplx.xowa.parsers.tblws.*; import gplx.xowa.parsers.xndes.*;
import gplx.xowa.xtns.*; import gplx.xowa.xtns.scribunto.*; import gplx.xowa.xtns.math.*;

@ -33,11 +33,12 @@ public class Xoae_page implements Xoa_page {
public Xow_wiki Wiki() {return wiki;}
public Xoa_ttl Ttl() {return ttl;} public Xoae_page Ttl_(Xoa_ttl v) {ttl = v; url.Wiki_bry_(wiki.Domain_bry()).Page_bry_(v.Full_url()); return this;} private Xoa_ttl ttl;
public Xoa_url Url() {return url;} public Xoae_page Url_(Xoa_url v) {url = v; return this;} private Xoa_url url = Xoa_url.blank();
public byte[] Url_bry_safe() {return url == null ? Bry_.Empty : url.Raw();}
public byte[] Url_bry_safe() {return Xoa_page_.Url_bry_safe(url, wiki, ttl);}
public Xopg_db_data Db() {return db;} private final Xopg_db_data db = new Xopg_db_data();
public Xopg_redirect_mgr Redirect_trail() {return redirect_trail;} private final Xopg_redirect_mgr redirect_trail = new Xopg_redirect_mgr();
public Xopg_html_data Html_data() {return html;} private final Xopg_html_data html = new Xopg_html_data();
public Xopg_hdump_data Hdump_mgr() {return hdump;} private final Xopg_hdump_data hdump = new Xopg_hdump_data();
public Xopg_wtxt_data Wtxt() {return wtxt;} private final Xopg_wtxt_data wtxt = new Xopg_wtxt_data();
public Xoa_page__commons_mgr Commons_mgr() {return commons_mgr;} private final Xoa_page__commons_mgr commons_mgr = new Xoa_page__commons_mgr();
public void Xtn_gallery_packed_exists_y_() {html.Xtn_gallery_packed_exists_y_();}
@ -50,15 +51,13 @@ public class Xoae_page implements Xoa_page {
public byte Edit_mode() {return edit_mode;} private byte edit_mode; public void Edit_mode_update_() {edit_mode = Xoa_page_.Edit_mode_update;}
public Xop_root_tkn Root() {return root;} public Xoae_page Root_(Xop_root_tkn v) {root = v; return this;} private Xop_root_tkn root;
public Xopg_wtxt_data Wtxt() {return wtxt;} private final Xopg_wtxt_data wtxt = new Xopg_wtxt_data();
public Xoh_cmd_mgr Html_cmd_mgr() {return html_cmd_mgr;} private Xoh_cmd_mgr html_cmd_mgr = new Xoh_cmd_mgr();
public Xof_xfer_queue File_queue() {return file_queue;} private Xof_xfer_queue file_queue = new Xof_xfer_queue();
public List_adp File_math() {return file_math;} private List_adp file_math = List_adp_.New();
public List_adp Lnki_list() {return lnki_list;} public void Lnki_list_(List_adp v) {this.lnki_list = v;} private List_adp lnki_list = List_adp_.New();
public Ref_itm_mgr Ref_mgr() {return ref_mgr;} private Ref_itm_mgr ref_mgr = new Ref_itm_mgr(); public void Ref_mgr_(Ref_itm_mgr v) {this.ref_mgr = v;}
public Xopg_popup_mgr Popup_mgr() {return popup_mgr;} private Xopg_popup_mgr popup_mgr = new Xopg_popup_mgr();
public byte[][] Category_list() {return category_list;} public Xoae_page Category_list_(byte[][] v) {category_list = v; return this;} private byte[][] category_list = new byte[0][];
public List_adp Slink_list() {return slink_list;} private List_adp slink_list = List_adp_.New();
public Wdata_external_lang_links_data Wdata_external_lang_links() {return wdata_external_lang_links;} private Wdata_external_lang_links_data wdata_external_lang_links = new Wdata_external_lang_links_data();
public int Bldr__ns_ord() {return bldr__ns_ord;} public void Bldr__ns_ord_(int v) {bldr__ns_ord = v;} private int bldr__ns_ord;

@ -17,10 +17,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa; import gplx.*;
import gplx.core.primitives.*; import gplx.core.brys.*; import gplx.core.ios.*;
import gplx.xowa.langs.*; import gplx.xowa.langs.cases.*;
import gplx.xowa.langs.*; import gplx.xowa.langs.msgs.*; import gplx.xowa.langs.cases.*;
import gplx.xowa.wikis.*; import gplx.xowa.wikis.domains.*; import gplx.xowa.wikis.metas.*; import gplx.xowa.wikis.data.site_stats.*; import gplx.xowa.wikis.ttls.*; import gplx.xowa.wikis.data.*; import gplx.xowa.wikis.xwikis.*; import gplx.xowa.addons.*;
import gplx.xowa.files.*; import gplx.xowa.files.repos.*; import gplx.xowa.files.origs.*; import gplx.xowa.files.bins.*; import gplx.fsdb.meta.*; import gplx.fsdb.*;
import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.htmls.utls.*; import gplx.xowa.htmls.core.hzips.*; import gplx.xowa.htmls.core.*; import gplx.xowa.htmls.bridges.dbuis.tbls.*; import gplx.xowa.htmls.hrefs.*;
import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.htmls.utls.*; import gplx.xowa.htmls.core.hzips.*; import gplx.xowa.htmls.core.*; import gplx.xowa.htmls.bridges.dbuis.tbls.*; import gplx.xowa.htmls.hrefs.*; import gplx.xowa.addons.wikis.ctgs.htmls.pageboxs.*;
import gplx.xowa.parsers.*;
import gplx.xowa.apps.urls.*;
public interface Xow_wiki extends Xow_ttl_parser, Gfo_invk {
@ -30,7 +30,7 @@ public interface Xow_wiki extends Xow_ttl_parser, Gfo_invk {
Xol_case_mgr Case_mgr();
byte[] Domain_bry(); // EX: en.wikipedia.org
String Domain_str();
int Domain_tid(); // Xow_domain_tid_.Int__wikipedia
int Domain_tid(); // Xow_domain_tid_.Tid__wikipedia
byte[] Domain_abrv(); // enwiki
Xow_domain_itm Domain_itm();
Xow_fsys_mgr Fsys_mgr();
@ -46,7 +46,10 @@ public interface Xow_wiki extends Xow_ttl_parser, Gfo_invk {
Xoh_page_wtr_mgr Html__wtr_mgr();
Xoh_href_wtr Html__href_wtr();
Xoh_lnki_bldr Html__lnki_bldr();
Xoctg_pagebox_wtr Html__ctg_pagebox_wtr();
boolean Html__css_installing(); void Html__css_installing_(boolean v);
Xow_msg_mgr Msg_mgr();
byte[] Wtxt__expand_tmpl(byte[] src);
Xow_mw_parser_mgr Mw_parser_mgr();
Xow_xwiki_mgr Xwiki_mgr();
Xow_wiki_props Props();

@ -25,11 +25,11 @@ import gplx.xowa.files.*; import gplx.xowa.files.repos.*; import gplx.xowa.files
import gplx.xowa.htmls.heads.*; import gplx.xowa.htmls.core.htmls.utls.*; import gplx.xowa.htmls.core.hzips.*; import gplx.xowa.htmls.core.*; import gplx.xowa.htmls.ns_files.*; import gplx.xowa.htmls.bridges.dbuis.tbls.*; import gplx.xowa.htmls.hrefs.*;
import gplx.xowa.bldrs.xmls.*; import gplx.xowa.bldrs.installs.*; import gplx.xowa.bldrs.setups.maints.*;
import gplx.xowa.parsers.*; import gplx.xowa.parsers.utils.*;
import gplx.xowa.wikis.ctgs.*;
import gplx.xowa.addons.wikis.ctgs.*;
import gplx.xowa.guis.cbks.*; import gplx.xowa.guis.views.*;
import gplx.xowa.xtns.gallery.*; import gplx.xowa.xtns.pfuncs.*;
import gplx.xowa.wikis.tdbs.*; import gplx.xowa.wikis.tdbs.hives.*;
import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.htmls.css.mgrs.*;
import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.htmls.css.mgrs.*; import gplx.xowa.addons.wikis.ctgs.htmls.pageboxs.*;
public class Xowe_wiki implements Xow_wiki, Gfo_invk, Gfo_evt_itm {
private boolean init_in_process = false;
public Xowe_wiki(Xoae_app app, Xol_lang_itm lang, Xow_ns_mgr ns_mgr, Xow_domain_itm domain_itm, Io_url wiki_dir) {
@ -64,8 +64,8 @@ public class Xowe_wiki implements Xow_wiki, Gfo_invk, Gfo_evt_itm {
eval_mgr = new Bfmtr_eval_wiki(this);
fragment_mgr = new Xow_fragment_mgr(this);
xtn_mgr = new Xow_xtn_mgr().Ctor_by_wiki(this);
if (domain_tid == Xow_domain_tid_.Int__home) {
wdata_wiki_tid = Xow_domain_tid_.Int__wikipedia;
if (domain_tid == Xow_domain_tid_.Tid__home) {
wdata_wiki_tid = Xow_domain_tid_.Tid__wikipedia;
wdata_wiki_lang = Xol_lang_itm_.Key_en;
}
else {
@ -105,6 +105,7 @@ public class Xowe_wiki implements Xow_wiki, Gfo_invk, Gfo_evt_itm {
public Xoh_page_wtr_mgr Html__wtr_mgr() {return html_mgr.Page_wtr_mgr();}
public Xoh_lnki_bldr Html__lnki_bldr() {return lnki_bldr;} private final Xoh_lnki_bldr lnki_bldr;
public Xoh_href_wtr Html__href_wtr() {return href_wtr;} private final Xoh_href_wtr href_wtr = new Xoh_href_wtr();
public Xoctg_pagebox_wtr Html__ctg_pagebox_wtr() {return ctg_pagebox_wtr;} private final Xoctg_pagebox_wtr ctg_pagebox_wtr = new Xoctg_pagebox_wtr();
public boolean Html__css_installing() {return html__css_installing;} public void Html__css_installing_(boolean v) {html__css_installing = v;} private boolean html__css_installing;
public Xow_url_parser Utl__url_parser() {return url__parser;} private final Xow_url_parser url__parser;
public Xow_mw_parser_mgr Mw_parser_mgr() {return mw_parser_mgr;} private final Xow_mw_parser_mgr mw_parser_mgr = new Xow_mw_parser_mgr();
@ -116,6 +117,7 @@ public class Xowe_wiki implements Xow_wiki, Gfo_invk, Gfo_evt_itm {
public Xog_cbk_mgr Gui__cbk_mgr() {return gui__cbk_mgr;} private final Xog_cbk_mgr gui__cbk_mgr = new Xog_cbk_mgr();
public Xowe_page_mgr Page_mgr() {return page_mgr;} private final Xowe_page_mgr page_mgr;
public Xop_sanitizer Sanitizer() {return sanitizer;} private final Xop_sanitizer sanitizer;
public byte[] Wtxt__expand_tmpl(byte[] src) {return parser_mgr.Main().Expand_tmpl(src);}
public Xow_hdump_mgr Html__hdump_mgr() {return html__hdump_mgr;} private final Xow_hdump_mgr html__hdump_mgr;
@ -132,7 +134,7 @@ public class Xowe_wiki implements Xow_wiki, Gfo_invk, Gfo_evt_itm {
public byte[] Commons_wiki_key() {return commons_wiki_key;} private byte[] commons_wiki_key = Xow_domain_itm_.Bry__commons;
public Xob_hive_mgr Hive_mgr() {return hive_mgr;} private Xob_hive_mgr hive_mgr;
public Xow_msg_mgr Msg_mgr() {return msg_mgr;} private Xow_msg_mgr msg_mgr;
public Xow_msg_mgr Msg_mgr() {return msg_mgr;} private final Xow_msg_mgr msg_mgr;
public Xow_fragment_mgr Fragment_mgr() {return fragment_mgr;} private Xow_fragment_mgr fragment_mgr;
public Bfmtr_eval_wiki Eval_mgr() {return eval_mgr;} private Bfmtr_eval_wiki eval_mgr;
public Bry_bfr_mkr Utl__bfr_mkr() {return utl__bry_bfr_mkr;} private final Bry_bfr_mkr utl__bry_bfr_mkr = new Bry_bfr_mkr();
@ -198,7 +200,7 @@ public class Xowe_wiki implements Xow_wiki, Gfo_invk, Gfo_evt_itm {
gplx.xowa.bldrs.setups.upgrades.Xoa_upgrade_mgr.Check(this);
// init ns_mgr
if (lang.Init_by_load()) {
if (domain_tid == Xow_domain_tid_.Int__wikipedia) // NOTE: if type is wikipedia, add "Wikipedia" as an alias; PAGE:en.w:pt.wikipedia.org/wiki/Página principal which redirects to Wikipedia:Página principal
if (domain_tid == Xow_domain_tid_.Tid__wikipedia) // NOTE: if type is wikipedia, add "Wikipedia" as an alias; PAGE:en.w:pt.wikipedia.org/wiki/Página principal which redirects to Wikipedia:Página principal
ns_mgr.Aliases_add(Xow_ns_.Tid__project, Xow_ns_.Alias__wikipedia);
special_mgr.Evt_lang_changed(lang);
}
@ -223,6 +225,7 @@ public class Xowe_wiki implements Xow_wiki, Gfo_invk, Gfo_evt_itm {
app.Api_root().Wikis().Get(domain_bry).Subscribe(this);
app.Site_cfg_mgr().Load(this);
app.Addon_mgr().Load_by_wiki(this);
ctg_pagebox_wtr.Init_by_wiki(this);
}
public void Rls() {
if (rls_list != null) {

@ -46,6 +46,7 @@ public class Xoax_addon_mgr {
, new gplx.xowa.addons.bldrs.exports .Export_addon()
, new gplx.xowa.addons.wikis.pages.randoms .Rndm_addon()
, new gplx.xowa.addons.bldrs.hdumps.diffs .Dumpdiff_addon()
, new gplx.xowa.addons.wikis.ctgs.bldrs .Xoax_ctg_bldr_addon()
// specials
, new gplx.xowa.addons.wikis.registrys .Wiki_registry_addon()
@ -53,7 +54,7 @@ public class Xoax_addon_mgr {
, new gplx.xowa.addons.bldrs.xodirs .Xobc_xodir_addon()
, new gplx.xowa.addons.bldrs.centrals .Xobc_task_addon()
, new gplx.xowa.addons.apps.helps.logs .Xolog_addon()
, new gplx.xowa.addons.wikis.pages.syncs .Sync_addon()
, new gplx.xowa.addons.wikis.pages.syncs .Xosync_addon()
// jsons
);

@ -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/>.
*/
//namespace gplx.xowa.addons.apps.cfgs.dbs {
// using gplx.dbs; using gplx.dbs.utls;
// class Xocfg_data_itm : Db_tbl {
// private final Dbmeta_fld_list flds = new Dbmeta_fld_list();
// private final String fld_itm_id, fld_itm_val, fld_itm_date;
// private final Db_conn conn;
// public Xocfg_data_itm(Db_conn conn) {
// this.conn = conn;
// this.tbl_name = "cfg_data_itm";
// this.fld_itm_id = flds.Add_int("itm_id"); // EX: '1'
// // ctx_id; app,wiki,ns
// this.fld_itm_date = flds.Add_str("itm_date", 32); // EX: '20160901_010203'
// this.fld_itm_val = flds.Add_str("itm_val", 4096); // EX: 'abc'
// conn.Rls_reg(this);
// }
// public String Tbl_name() {return tbl_name;} private final String tbl_name;
// public void Create_tbl() {conn.Meta_tbl_create(Dbmeta_tbl_itm.New(tbl_name, flds));}
// public void Upsert(int itm_id, String itm_date, String itm_val) {
// Db_tbl__crud_.Upsert(conn, tbl_name, flds, String_.Ary(fld_itm_id), itm_id, itm_date, itm_val);
// }
// public void Rls() {}
// }
// class Xocfg_meta_itm : Db_tbl {
// private final Dbmeta_fld_list flds = new Dbmeta_fld_list();
// private final String fld_grp_id, fld_itm_id, fld_itm_sort, fld_itm_key, fld_scope_id, fld_type_id, fld_itm_dflt;
// private final Db_conn conn;
// public Xocfg_meta_itm(Db_conn conn) {
// this.conn = conn;
// this.tbl_name = "cfg_meta_itm";
// this.fld_grp_id = flds.Add_int("grp_id"); // EX: '1'
// this.fld_itm_id = flds.Add_int("itm_id"); // EX: '2'
// this.fld_itm_sort = flds.Add_int("itm_sort"); // EX: '3'
// this.fld_scope_id = flds.Add_int("itm_scope_id"); // EX: '1'; REF: cfg_meta_scope; ENUM: app-only, wiki-only, ...
// this.fld_type_id = flds.Add_int("itm_type_id"); // EX: '1'; REF: cfg_meta_type; ENUM: int, String, ...
// this.fld_itm_key = flds.Add_str("itm_key", 255); // EX: 'cfg_1'
// this.fld_itm_dflt = flds.Add_str("itm_dflt", 4096); // EX: 'abc'
// // display_name
// // help_text
// // locale
// conn.Rls_reg(this);
// }
// public String Tbl_name() {return tbl_name;} private final String tbl_name;
// public void Create_tbl() {conn.Meta_tbl_create(Dbmeta_tbl_itm.New(tbl_name, flds));}
// public void Upsert(int grp_id, int itm_id, int itm_sort, int scope_id, int type_id, String itm_key, String itm_dflt) {
// Db_tbl__crud_.Upsert(conn, tbl_name, flds, String_.Ary(fld_grp_id, fld_itm_id), grp_id, itm_id, itm_sort, scope_id, type_id, itm_key, itm_dflt);
// }
// public void Rls() {}
// }
// class Xocfg_meta_grp : Db_tbl {
// private final Dbmeta_fld_list flds = new Dbmeta_fld_list();
// private final String fld_grp_id, fld_grp_key;
// private final Db_conn conn;
// public Xocfg_meta_grp(Db_conn conn) {
// this.conn = conn;
// this.tbl_name = "cfg_meta_grp";
// this.fld_grp_id = flds.Add_int("grp_id");
// this.fld_grp_key = flds.Add_str("grp_key", 255);
// // display
// conn.Rls_reg(this);
// }
// public String Tbl_name() {return tbl_name;} private final String tbl_name;
// public void Create_tbl() {conn.Meta_tbl_create(Dbmeta_tbl_itm.New(tbl_name, flds));}
// public void Upsert(int grp_id, String grp_key) {
// Db_tbl__crud_.Upsert(conn, tbl_name, flds, String_.Ary(fld_grp_id), grp_id, grp_key);
// }
// public void Rls() {}
// }
// class Xocfg_meta_grp_map : Db_tbl {
// private final Dbmeta_fld_list flds = new Dbmeta_fld_list();
// private final String fld_map_src, fld_map_trg, fld_map_sort;
// private final Db_conn conn;
// public Xocfg_meta_grp_map(Db_conn conn) {
// this.conn = conn;
// this.tbl_name = "cfg_meta_grp_map";
// this.fld_map_src = flds.Add_int("map_src");
// this.fld_map_trg = flds.Add_int("map_trg");
// this.fld_map_sort = flds.Add_int("map_sort");
// conn.Rls_reg(this);
// }
// public String Tbl_name() {return tbl_name;} private final String tbl_name;
// public void Create_tbl() {conn.Meta_tbl_create(Dbmeta_tbl_itm.New(tbl_name, flds));}
// public void Upsert(int map_src, int map_trg, int map_sort) {
// Db_tbl__crud_.Upsert(conn, tbl_name, flds, String_.Ary(fld_map_src), map_src, map_trg, map_sort);
// }
// public void Rls() {}
// }
///*
//EXEC cfg_select 'xowa.wiki.page.sync', 'scope'
//
//SELECT @grp_id = grp_id FROM grp WHERE key = 'xowa.wiki.page.sync';
//@aboe = SELECT * FROM grp_map WHERE owner_id = @grp_id ORDER BY sort
//SELECT * FROM meta_itm WHERE grp_id IN (@above)
//
//{{#grp}}
// {{#itm_key}}
// Coalesce({{#itm_val}}, {{#itm_dflt}})
// {{#itm_dirty}}
// {{#itm_notes}}
//{{#grp}}
//
//grp_0 -> Name of page
//grp_1 -> H2
//grp_2 -> H3
//...
//*/
//}

@ -33,6 +33,7 @@ public abstract class Xobc_cmd__base implements Xobc_cmd_itm {
public long Prog_data_cur() {return data_cur;} private long data_cur; public void Prog_data_cur_(long v) {this.data_cur = v;}
public long Prog_data_end() {return data_end;} private long data_end; public void Prog_data_end_(long v) {this.data_end = v;}
public byte Prog_status() {return status;} private byte status = Gfo_prog_ui_.Status__init; public void Prog_status_(byte v) {status = v;}
public void Prog_notify_by_msg(String msg) {task_mgr.Work_mgr().On_stat(task_id, msg);}
public boolean Canceled() {return status == Gfo_prog_ui_.Status__suspended;}
public void Cancel() {status = Gfo_prog_ui_.Status__suspended;}
@ -64,7 +65,7 @@ public abstract class Xobc_cmd__base implements Xobc_cmd_itm {
Gfo_log_.Instance.Info("xobc_cmd task end", "task_id", task_id, "step_id", step_id, "cmd_id", cmd_id);
switch (status) {
case Gfo_prog_ui_.Status__suspended: task_mgr.Work_mgr().On_suspended(this); break;
case Gfo_prog_ui_.Status__fail: task_mgr.Work_mgr().On_fail(this, Bool_.N, cmd_exec_err); break;
case Gfo_prog_ui_.Status__fail: task_mgr.Work_mgr().On_fail(this, this.Cmd_fail_resumes(), cmd_exec_err); break;
case Gfo_prog_ui_.Status__working:
this.Prog_notify_and_chk_if_suspended(data_end, data_end); // fire one more time for 100%; note that 100% may not fire due to timer logic below
task_mgr.Work_mgr().On_done(this);

@ -18,10 +18,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.xowa.addons.bldrs.centrals.cmds; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*; import gplx.xowa.addons.bldrs.centrals.*;
import gplx.core.progs.*; import gplx.core.net.downloads.*;
public class Xobc_cmd__download extends Xobc_cmd__base {
private final Xobc_task_mgr task_mgr;
private final String src_url; private final Io_url trg_url;
private final long expd_size;
private final Http_download_wkr wkr;
public Xobc_cmd__download(Xobc_task_mgr task_mgr, int task_id, int step_id, int cmd_id, String src_url, Io_url trg_url, long file_size_zip) {super(task_mgr, task_id, step_id, cmd_id);
this.task_mgr = task_mgr;
this.src_url = src_url; this.trg_url = trg_url; this.expd_size = file_size_zip;
this.wkr = Http_download_wkr_.Proto.Make_new();
this.Prog_data_end_(expd_size);
@ -31,8 +33,31 @@ public class Xobc_cmd__download extends Xobc_cmd__base {
@Override public boolean Cmd_suspendable() {return true;}
@Override protected void Cmd_exec_hook(Xobc_cmd_ctx ctx) {
if (wkr.Exec(this, src_url, trg_url, expd_size) == Gfo_prog_ui_.Status__fail)
this.Cmd_exec_err_(wkr.Fail_msg());
int error_wait = 10000, error_tries_max = 6, error_tries_cur = 0; // retry every 10 seconds for a total of 6 tries (1 min)
while (true) {
long trg_size_bgn = Io_mgr.Instance.QueryFil(wkr.Tmp_url()).Size();
byte status = wkr.Exec(this, src_url, trg_url, expd_size);
if (status == Gfo_prog_ui_.Status__fail) {
// check if anything more downloaded; if so, then reset to 0; DATE:2016-09-03
long trg_size_cur = Io_mgr.Instance.QueryFil(wkr.Tmp_url()).Size();
if (trg_size_cur > trg_size_bgn) {
error_tries_cur = 0;
trg_size_bgn = trg_size_cur;
}
// retry
if (error_tries_cur++ < error_tries_max) {
task_mgr.Work_mgr().On_stat(this.Task_id(), String_.Format("connection interrupted: retrying in {0} seconds; attempt {1} of {2}", error_wait / 1000, error_tries_cur, error_tries_max));
Gfo_usr_dlg_.Instance.Log_many("", "", "xobc_cmd task download interrupted; ~{0} ~{1} ~{2} ~{3}", this.Task_id(), this.Step_id(), trg_url, Io_mgr.Instance.QueryFil(trg_url).Size());
gplx.core.threads.Thread_adp_.Sleep(error_wait);
continue;
}
this.Cmd_exec_err_(wkr.Fail_msg());
break;
}
else
break;
}
Gfo_log_.Instance.Info("xobc_cmd task download", "task_id", this.Task_id(), "step_id", this.Step_id(), "trg_url", trg_url, "trg_len", Io_mgr.Instance.QueryFil(trg_url).Size());
}
@Override public void Cmd_cleanup() {

@ -137,4 +137,7 @@ public class Xobc_task_regy__work extends Xobc_task_regy__base {
Xod_power_mgr_.Instance.Wake_lock__rls("task_mgr");
task_mgr.Send_json("xo.bldr.work.prog__fail__recv", Gfobj_nde.New().Add_int("task_id", task.Task_id()).Add_str("err", msg).Add_bool("resume", resume));
}
public void On_stat(int task_id, String msg) {
task_mgr.Send_json("xo.bldr.work.prog__stat__recv", Gfobj_nde.New().Add_int("task_id", task_id).Add_str("msg", msg));
}
}

@ -29,7 +29,7 @@ import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.cmds.*; import gplx.xowa.bldrs.
import gplx.xowa.addons.bldrs.files.dbs.*; import gplx.xowa.addons.bldrs.mass_parses.parses.*; import gplx.xowa.addons.bldrs.mass_parses.parses.utls.*;
import gplx.xowa.addons.bldrs.wmdumps.imglinks.*;
public class Xobldr__lnki_temp__create extends Xob_dump_mgr_base implements gplx.xowa.parsers.lnkis.files.Xop_file_logger {
private Xob_lnki_temp_tbl tbl; private boolean wdata_enabled = true, xtn_ref_enabled = true, gen_html, gen_hdump;
private Xob_lnki_temp_tbl tbl; private boolean wdata_enabled = true, xtn_ref_enabled = true, gen_html, gen_hdump, load_all_imglinks;
private Xop_log_invoke_wkr invoke_wkr; private Xop_log_property_wkr property_wkr;
private boolean ns_file_is_case_match_all = true; private Xowe_wiki commons_wiki;
private final Xob_hdump_bldr hdump_bldr = new Xob_hdump_bldr(); private Vnt_convert_lang converter_lang;
@ -65,7 +65,7 @@ public class Xobldr__lnki_temp__create extends Xob_dump_mgr_base implements gplx
// create imglinks
Xof_orig_wkr__img_links orig_wkr = new Xof_orig_wkr__img_links(wiki);
wiki.File__orig_mgr().Wkrs__set(orig_wkr);
Xof_orig_wkr__img_links_.Load_all(orig_wkr);
if (load_all_imglinks) Xof_orig_wkr__img_links_.Load_all(orig_wkr);
Xow_wiki_utl_.Clone_repos(wiki);
@ -162,6 +162,7 @@ public class Xobldr__lnki_temp__create extends Xob_dump_mgr_base implements gplx
else if (ctx.Match(k, Invk_ns_ids_)) ns_ids = Int_.Ary_parse(m.ReadStr("v"), "|");
else if (ctx.Match(k, Invk_ns_ids_by_aliases)) ns_ids = Xobldr__lnki_temp__create_.Ns_ids_by_aliases(wiki, m.ReadStrAry("v", "|"));
else if (ctx.Match(k, Invk_gen_html_)) gen_html = m.ReadYn("v");
else if (ctx.Match(k, Invk__load_all_imglinks_)) load_all_imglinks = m.ReadYn("v");
else if (ctx.Match(k, Invk_hdump_bldr)) return hdump_bldr;
else if (ctx.Match(k, Invk_property_wkr)) return this.Property_wkr();
else if (ctx.Match(k, Invk_invoke_wkr)) return this.Invoke_wkr();
@ -171,6 +172,7 @@ public class Xobldr__lnki_temp__create extends Xob_dump_mgr_base implements gplx
private static final String Invk_wdata_enabled_ = "wdata_enabled_", Invk_xtn_ref_enabled_ = "xtn_ref_enabled_", Invk_gen_html_ = "gen_html_"
, Invk_ns_ids_ = "ns_ids_", Invk_ns_ids_by_aliases = "ns_ids_by_aliases"
, Invk_invoke_wkr = "invoke_wkr", Invk_property_wkr = "property_wkr", Invk_hdump_bldr = "hdump_bldr"
, Invk__load_all_imglinks_ = "load_all_imglinks_"
;
public static final String BLDR_CMD_KEY = "file.lnki_temp";
@Override public String Cmd_key() {return BLDR_CMD_KEY;}

@ -66,7 +66,7 @@ class Xobc_info_html extends Xow_special_wtr__base {
String src_dir = host_eval.Eval_src_dir(data_db, host_id, wiki_domain);
String[] ary = String_.Split(key, "|");
ary[0] = String_.new_u8(wiki_domain.Abrv_wm());
torrent_fil = String_.Format("{0}Xowa_{1}_latest_archive.torrent", src_dir, wiki_domain.Abrv_wm(), ary[1]); // EX: https://archive.org/download/Xowa_dewiki_latest/Xowa_dewiki_latest_archive.torrent
torrent_fil = String_.Format("{0}Xowa_{1}wiki_latest_archive.torrent", src_dir, wiki_domain.Lang_orig_key()); // EX: https://archive.org/download/Xowa_dewiki_latest/Xowa_dewiki_latest_archive.torrent
}
return new Xobc_info_doc
@ -77,6 +77,9 @@ class Xobc_info_html extends Xow_special_wtr__base {
, step_urls
);
}
public static String Make_torrent_fil(String src_dir, Xow_domain_itm domain) {
return String_.Format("{0}Xowa_{1}wiki_latest_archive.torrent", src_dir, domain.Lang_orig_key()); // EX: https://archive.org/download/Xowa_dewiki_latest/Xowa_dewiki_latest_archive.torrent
}
@Override protected void Bld_tags(Xoa_app app, Io_url addon_dir, Xopage_html_data page_data) {
Xopg_tag_mgr head_tags = page_data.Head_tags();
Xopg_tag_wtr_.Add__xocss (head_tags, app.Fsys_mgr().Http_root());

@ -0,0 +1,29 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.bldrs.infos; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*;
import org.junit.*; import gplx.core.tests.*; import gplx.xowa.wikis.domains.*;
public class Xobc_info_html__tst {
private final Xobc_info_html__fxt fxt = new Xobc_info_html__fxt();
@Test public void Torrent__en_w() {fxt.Test__torrent_link("en.wikipedia.org" , "https://archive.org/download/Xowa_enwiki_latest_archive.torrent");}
@Test public void Torrent__fr_d() {fxt.Test__torrent_link("fr.wiktionary.org" , "https://archive.org/download/Xowa_frwiki_latest_archive.torrent");}
}
class Xobc_info_html__fxt {
public void Test__torrent_link(String domain_str, String expd) {
Gftest.Eq__str(expd, Xobc_info_html.Make_torrent_fil("https://archive.org/download/", Xow_domain_itm_.parse(Bry_.new_u8(domain_str))));
}
}

@ -52,7 +52,8 @@ class Xomp_make_lnki {
if (wkr_uid_max > tmp_xomp_uid_max)
tmp_xomp_uid_max = wkr_uid_max;
}
if (tmp_xomp_uid_max >= max_xomp_uid || tmp_xomp_uid_max == -1) break; // if max_xomp_uid seen, break; note that ">" necessary because max_xomp_uid may not be in set of wkrs;
// NOTE: not ">=" else small wikis will fail with 0 images; EX:cs.q; DATE:2016-09-04
if (tmp_xomp_uid_max > max_xomp_uid || tmp_xomp_uid_max == -1) break; // if max_xomp_uid seen, break; note that ">" necessary because max_xomp_uid may not be in set of wkrs;
cur_xomp_uid += uid_count; // note that this sequentially counts up by uid_count (1000), so inevitable that cur_xomp_uid will exceed wkr_uid_max
Gfo_usr_dlg_.Instance.Prog_many("", "", "building lnki_temp; cur_xomp_uid=~{0}", cur_xomp_uid);
Save_rows(rows, lnki_temp_tbl);

@ -30,7 +30,7 @@ public class Xomp_parse_mgr {
Xomp_mgr_db mgr_db = Xomp_mgr_db.New__load(cfg.Mgr_url());
// init page_pool
Xomp_page_pool_loader page_pool_loader = new Xomp_page_pool_loader(wiki, mgr_db.Conn(), cfg.Num_pages_in_pool());
Xomp_page_pool_loader page_pool_loader = new Xomp_page_pool_loader(wiki, mgr_db.Conn(), cfg.Num_pages_in_pool(), cfg.Show_msg__fetched_pool());
Xomp_page_pool page_pool = new Xomp_page_pool(page_pool_loader, cfg.Num_pages_per_wkr());
Xomp_prog_mgr prog_mgr = new Xomp_prog_mgr();
prog_mgr.Init(page_pool_loader.Get_pending_count(), cfg.Progress_interval());

@ -25,6 +25,7 @@ public class Xomp_parse_mgr_cfg implements Gfo_invk {
public int Commit_interval() {return commit_interval;} private int commit_interval = 10000;
public int Cleanup_interval() {return cleanup_interval;} private int cleanup_interval = 50; // setting at 1000 uses lots of memory
public boolean Hdump_enabled() {return hdump_enabled;} private boolean hdump_enabled = true;
public boolean Hdump_catboxs() {return hdump_catboxs;} private boolean hdump_catboxs = false;
public boolean Hzip_enabled() {return hzip_enabled;} private boolean hzip_enabled = true;
public boolean Hdiff_enabled() {return hdiff_enabled;} private boolean hdiff_enabled = true;
public boolean Log_file_lnkis() {return log_file_lnkis;} private boolean log_file_lnkis = true;
@ -33,6 +34,7 @@ public class Xomp_parse_mgr_cfg implements Gfo_invk {
public byte Zip_tid() {return zip_tid;} private byte zip_tid = Io_stream_.Tid_gzip;
public Io_url Mgr_url() {return mgr_url;} private Io_url mgr_url;
public String Wkr_machine_name() {return wkr_machine_name;} private String wkr_machine_name;
public boolean Show_msg__fetched_pool() {return show_msg__fetched_pool;} private boolean show_msg__fetched_pool;
public void Init(Xowe_wiki wiki) {
if (num_wkrs == -1) num_wkrs = gplx.core.envs.Runtime_.Cpu_count();
if (num_pages_in_pool == -1) num_pages_in_pool = num_wkrs * 1000;
@ -41,21 +43,23 @@ public class Xomp_parse_mgr_cfg implements Gfo_invk {
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk__num_wkrs_)) num_wkrs = m.ReadInt("v");
else if (ctx.Match(k, Invk__num_pages_in_pool_)) num_pages_in_pool = m.ReadInt("v");
else if (ctx.Match(k, Invk__num_pages_per_wkr_)) num_pages_per_wkr = m.ReadInt("v");
else if (ctx.Match(k, Invk__progress_interval_)) progress_interval = m.ReadInt("v");
else if (ctx.Match(k, Invk__commit_interval_)) commit_interval = m.ReadInt("v");
else if (ctx.Match(k, Invk__cleanup_interval_)) cleanup_interval = m.ReadInt("v");
else if (ctx.Match(k, Invk__hdump_enabled_)) hdump_enabled = m.ReadBool("v");
else if (ctx.Match(k, Invk__hzip_enabled_)) hzip_enabled = m.ReadBool("v");
else if (ctx.Match(k, Invk__hdiff_enabled_)) hdiff_enabled = m.ReadBool("v");
else if (ctx.Match(k, Invk__zip_tid_)) zip_tid = m.ReadByte("v");
else if (ctx.Match(k, Invk__load_all_templates_)) load_all_templates = m.ReadYn("v");
else if (ctx.Match(k, Invk__load_all_imglnks_)) load_all_imglnks = m.ReadYn("v");
else if (ctx.Match(k, Invk__manual_now_)) Datetime_now.Manual_and_freeze_(m.ReadDate("v"));
else if (ctx.Match(k, Invk__mgr_url_)) mgr_url = m.ReadIoUrl("v");
else if (ctx.Match(k, Invk__wkr_machine_name_)) wkr_machine_name = m.ReadStr("v");
if (ctx.Match(k, Invk__num_wkrs_)) num_wkrs = m.ReadInt("v");
else if (ctx.Match(k, Invk__num_pages_in_pool_)) num_pages_in_pool = m.ReadInt("v");
else if (ctx.Match(k, Invk__num_pages_per_wkr_)) num_pages_per_wkr = m.ReadInt("v");
else if (ctx.Match(k, Invk__progress_interval_)) progress_interval = m.ReadInt("v");
else if (ctx.Match(k, Invk__commit_interval_)) commit_interval = m.ReadInt("v");
else if (ctx.Match(k, Invk__cleanup_interval_)) cleanup_interval = m.ReadInt("v");
else if (ctx.Match(k, Invk__hdump_enabled_)) hdump_enabled = m.ReadYn("v");
else if (ctx.Match(k, Invk__hzip_enabled_)) hzip_enabled = m.ReadYn("v");
else if (ctx.Match(k, Invk__hdiff_enabled_)) hdiff_enabled = m.ReadYn("v");
else if (ctx.Match(k, Invk__zip_tid_)) zip_tid = m.ReadByte("v");
else if (ctx.Match(k, Invk__load_all_templates_)) load_all_templates = m.ReadYn("v");
else if (ctx.Match(k, Invk__load_all_imglnks_)) load_all_imglnks = m.ReadYn("v");
else if (ctx.Match(k, Invk__manual_now_)) Datetime_now.Manual_and_freeze_(m.ReadDate("v"));
else if (ctx.Match(k, Invk__mgr_url_)) mgr_url = m.ReadIoUrl("v");
else if (ctx.Match(k, Invk__wkr_machine_name_)) wkr_machine_name = m.ReadStr("v");
else if (ctx.Match(k, Invk__show_msg__fetched_pool_)) show_msg__fetched_pool = m.ReadYn("v");
else if (ctx.Match(k, Invk__hdump_catboxes_)) hdump_catboxs = m.ReadYn("v");
else return Gfo_invk_.Rv_unhandled;
return this;
}
@ -64,6 +68,8 @@ public class Xomp_parse_mgr_cfg implements Gfo_invk {
, Invk__progress_interval_ = "progress_interval_", Invk__commit_interval_ = "commit_interval_", Invk__cleanup_interval_ = "cleanup_interval_"
, Invk__hdump_enabled_ = "hdump_enabled_", Invk__hzip_enabled_ = "hzip_enabled_", Invk__hdiff_enabled_ = "hdiff_enabled_", Invk__zip_tid_ = "zip_tid_"
, Invk__load_all_templates_ = "load_all_templates_", Invk__load_all_imglnks_ = "load_all_imglnks_", Invk__manual_now_ = "manual_now_"
, Invk__hdump_catboxes_ = "hdump_catboxes_"
, Invk__mgr_url_ = "mgr_url_", Invk__wkr_machine_name_ = "wkr_machine_name_"
, Invk__show_msg__fetched_pool_ = "show_msg__fetched_pool_"
;
}

@ -22,11 +22,13 @@ public class Xomp_page_pool_loader {
private final Xow_wiki wiki;
private final int num_pages_per_load;
private final Db_attach_mgr attach_mgr;
public Xomp_page_pool_loader(Xow_wiki wiki, Db_conn make_conn, int num_pages_per_load) {
private final boolean show_msg__fetched_pool;
public Xomp_page_pool_loader(Xow_wiki wiki, Db_conn make_conn, int num_pages_per_load, boolean show_msg__fetched_pool) {
this.wiki = wiki;
this.make_conn = make_conn;
this.attach_mgr = new Db_attach_mgr(make_conn);
this.num_pages_per_load = num_pages_per_load;
this.show_msg__fetched_pool = show_msg__fetched_pool;
}
public Db_conn Conn() {return make_conn;} private final Db_conn make_conn;
public int Get_pending_count() {
@ -50,7 +52,8 @@ public class Xomp_page_pool_loader {
int uid_new = 0;
try {uid_new = this.Load_from_db(rv, uid_db);}
finally {lock_mgr.Uid_prv__rls(machine_name, uid_new);}
Gfo_usr_dlg_.Instance.Note_many("", "", "fetched new pool: old=~{0} new=~{1}", uid_db, uid_new);
if (show_msg__fetched_pool)
Gfo_usr_dlg_.Instance.Note_many("", "", "fetched new pool: old=~{0} new=~{1}", uid_db, uid_new);
return rv;
}
private int Load_from_db(List_adp list, int uid_prv) {

@ -67,8 +67,8 @@ public class Xomp_parse_wkr implements Gfo_invk {
wiki.File__orig_mgr().Wkrs__set(file_orig_wkr);
wiki.File_mgr().Fsdb_mode().Tid__v2__mp__y_();
// disable categories else progress messages written (also for PERF)
wiki.Html_mgr().Page_wtr_mgr().Wkr(gplx.xowa.wikis.pages.Xopg_page_.Tid_read).Ctgs_enabled_(false);
// disable categories b/c categories will be retrieved at run-time
wiki.Html_mgr().Page_wtr_mgr().Wkr(gplx.xowa.wikis.pages.Xopg_page_.Tid_read).Ctgs_enabled_(cfg.Hdump_catboxs());
// enable lnki_temp
Xomp_lnki_temp_wkr logger = null;

@ -27,7 +27,7 @@ public class Imglnk_bldr_cmd extends Xob_sql_dump_base implements Sql_file_parse
@Override public String Sql_file_name() {return "imagelinks";}
@Override public void Cmd_bgn_hook(Xob_bldr bldr, Sql_file_parser parser) {
parser.Fld_cmd_(this).Flds_req_idx_(3, 0, 1);
parser.Save_csv_n_().Fld_cmd_(this).Flds_req_idx_(3, 0, 1);
mgr = new Imglnk_bldr_mgr(wiki);
}
public void Exec(byte[] src, byte[] fld_key, int fld_idx, int fld_bgn, int fld_end, Bry_bfr file_bfr, Sql_file_parser_data data) {

@ -62,15 +62,15 @@ public class Xof_orig_wkr__img_links implements Xof_orig_wkr {
hash.Add(itm.Ttl(), itm);
}
private Xof_orig_itm Load_from_db(byte[] ttl) {
if (imglnk_conn == null)
imglnk_conn = Xob_db_file.New__img_link(wiki).Conn();
Xof_orig_itm rv = Xof_orig_wkr__img_links_.Load_itm(this, imglnk_conn, wiki, ttl);
if (rv == Xof_orig_itm.Null)
rv = Missing;
synchronized (hash) { // LOCK:used by multiple threads in xomp
synchronized (hash) { // LOCK:orig_wkr is shared by multiple threads; NullPointerException on statement sometimes when concurrent; DATE:2016-09-03
if (imglnk_conn == null)
imglnk_conn = Xob_db_file.New__img_link(wiki).Conn();
Xof_orig_itm rv = Xof_orig_wkr__img_links_.Load_itm(this, imglnk_conn, wiki, ttl);
if (rv == Xof_orig_itm.Null)
rv = Missing;
hash.Add(ttl, rv);
return rv;
}
return rv;
}
private static final Xof_orig_itm Missing = new Xof_orig_itm(Byte_.Max_value_127, Bry_.Empty, -1, -1, -1, Bry_.Empty);
}

@ -0,0 +1,58 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.htmls.sidebars; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.htmls.*;
import gplx.core.brys.*; import gplx.core.brys.fmts.*;
class Xoh_sidebar_htmlr {
public static byte[] To_html(Bry_bfr bfr, Xowe_wiki wiki, List_adp grps) {
Xoh_sidebar_itms_fmtr itms_fmtr = new Xoh_sidebar_itms_fmtr();
int len = grps.Count();
boolean popups_enabled = wiki.Appe().Api_root().Html().Modules().Popups().Enabled();
for (int i = 0; i < len; ++i) {
Xoh_sidebar_itm grp = (Xoh_sidebar_itm)grps.Get_at(i);
itms_fmtr.Init_by_grp(popups_enabled, grp);
fmt.Bld_many(bfr, grp.Id(), grp.Text(), itms_fmtr);
}
return bfr.To_bry_and_clear();
}
private static final Bry_fmt fmt = Bry_fmt.Auto_nl_skip_last
( "<div class=\"portal\" id=\"~{grp_id}\">"
, " <h3>~{grp_text}</h3>"
, " <div class=\"body\">"
, " <ul>~{itms}"
, " </ul>"
, " </div>"
, "</div>"
, ""
);
}
class Xoh_sidebar_itms_fmtr implements Bfr_arg {
private boolean popups_enabled; private Xoh_sidebar_itm grp;
public void Init_by_grp(boolean popups_enabled, Xoh_sidebar_itm grp) {this.popups_enabled = popups_enabled; this.grp = grp;}
public void Bfr_arg__add(Bry_bfr bfr) {
String itm_cls = popups_enabled ? " class='xowa-hover-off'" : "";
int len = grp.Subs__len();
for (int i = 0; i < len; ++i) {
Xoh_sidebar_itm itm = grp.Subs__get_at(i);
fmt.Bld_many(bfr, itm.Id(), itm.Href(), itm_cls, itm.Atr_accesskey_and_title(), itm.Text());
}
}
private final Bry_fmt fmt = Bry_fmt.Auto_nl_skip_last
( ""
, " <li id=\"~{itm_id}\"><a href=\"~{itm_href}\"~{itm_cls}~{itm_accesskey_and_title}>~{itm_text}</a></li>"
);
}

@ -0,0 +1,49 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.htmls.sidebars; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.htmls.*;
public class Xoh_sidebar_itm {
public Xoh_sidebar_itm(boolean tid_is_itm, byte[] text_key, byte[] text_val, byte[] href) {
this.tid_is_itm = tid_is_itm;
this.id = gplx.langs.htmls.encoders.Gfo_url_encoder_.Id.Encode(Bry_.Add(CONST_id_prefix, text_key)); // build id; EX:"n-encoded_id"
this.text = text_val;
this.href = href;
}
public boolean Tid_is_itm() {return tid_is_itm;} private final boolean tid_is_itm;
public byte[] Id() {return id;} private final byte[] id;
public byte[] Text() {return text;} private final byte[] text;
public byte[] Href() {return href;} private final byte[] href;
public byte[] Title() {return title;} private byte[] title;
public byte[] Accesskey() {return accesskey;} private byte[] accesskey;
public byte[] Atr_accesskey_and_title() {return atr_accesskey_and_title;} private byte[] atr_accesskey_and_title;
public int Subs__len() {return subs.Count();} private final List_adp subs = List_adp_.New();
public Xoh_sidebar_itm Subs__get_at(int i) {return (Xoh_sidebar_itm)subs.Get_at(i);}
public Xoh_sidebar_itm Subs__add(Xoh_sidebar_itm... ary) {
int len = ary.length;
for (int i = 0; i < len; ++i)
subs.Add(ary[i]);
return this;
}
public void Init_by_title_and_accesskey(byte[] title, byte[] accesskey, byte[] atr_accesskey_and_title) {
this.title = title;
this.accesskey = accesskey;
this.atr_accesskey_and_title = atr_accesskey_and_title;
}
private static final byte[] CONST_id_prefix = Bry_.new_a7("n-");
}

@ -0,0 +1,53 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.htmls.sidebars; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.htmls.*;
import gplx.xowa.langs.*; import gplx.xowa.langs.msgs.*;
import gplx.xowa.wikis.domains.*; import gplx.xowa.wikis.data.*; import gplx.xowa.wikis.nss.*;
public class Xoh_sidebar_mgr {
public Xoh_sidebar_mgr(Xowe_wiki wiki) {this.wiki = wiki;} private final Xowe_wiki wiki;
public List_adp Grps() {return grps;} private final List_adp grps = List_adp_.New(); // TEST:
public byte[] Html_bry() {return html_bry;} private byte[] html_bry;
public void Init_by_wiki() {
try {
Bry_bfr tmp_bfr = Bry_bfr_.New();
byte[] sidebar = Get_sidebar_or_null(tmp_bfr, wiki);
if (sidebar != null) Make(tmp_bfr, sidebar);
} catch (Exception e) {
wiki.Appe().Usr_dlg().Warn_many("", "", "sidebar failed: wiki=~{0} err=~{1}", wiki.Domain_str(), Err_.Message_gplx_log(e));
}
}
private byte[] Get_sidebar_or_null(Bry_bfr tmp_bfr, Xowe_wiki wiki) {
// if home, always return null
if (wiki.Domain_tid() == Xow_domain_tid_.Tid__home) return null;
// check msg_mgr; note that this checks (a) en.wikipedia.org/wiki/MediaWiki:Sidebar; (b) "sidebar" in en.gfs
Xol_msg_itm rv_msg = Xol_msg_mgr_.Get_msg_itm(tmp_bfr, wiki, wiki.Lang(), Ttl__sidebar);
// if found in MediaWiki:Sidebar, always return it
byte[] rv = rv_msg.Val();
if (rv_msg.Defined_in() == Xol_msg_itm.Defined_in__wiki && Bry_.Len_gt_0(rv)) return rv;
// sidebar is either (a) in lang.gfs (wikia; wmf wikis without MediaWiki:Sidebar), or (b) not even in lang.gfs (wmf wikis in lang.gfs without "lang.gfs"; EX:de.gfs)
return null;
}
public void Make(Bry_bfr tmp_bfr, byte[] src) { // TEST:
Xoh_sidebar_parser.Parse(tmp_bfr, wiki, grps, src);
html_bry = Xoh_sidebar_htmlr.To_html(tmp_bfr, wiki, grps);
}
private static final byte[] Ttl__sidebar = Bry_.new_a7("Sidebar"); // MediaWiki:Sidebar
}

@ -0,0 +1,234 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.htmls.sidebars; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.htmls.*;
import org.junit.*;
import gplx.xowa.langs.*; import gplx.xowa.langs.msgs.*;
public class Xoh_sidebar_mgr_tst {
@Before public void init() {fxt.Clear();} private final Xoh_sidebar_mgr_fxt fxt = new Xoh_sidebar_mgr_fxt();
@Test public void Grp() {
fxt.Init__msg__grp("key", "text", "title");
fxt.Exec__make("* key");
fxt.Test__objs(fxt.Make__grp("text", "title"));
}
@Test public void Grp_missing_msg() {
fxt.Exec__make("* key");
fxt.Test__objs(fxt.Make__grp("key", Null_str));
}
@Test public void Itm() {
fxt.Init__msg__itm("href_key", "main_key", "text", "title", "accesskey", "href");
fxt.Exec__make("** href_key|main_key");
fxt.Test__objs(fxt.Make__itm("text", "title", "accesskey", "/wiki/Href"));
}
@Test public void Itm_missing_msg() {
fxt.Exec__make("** href_key|main_key");
fxt.Test__objs(fxt.Make__itm("main_key", Null_str, Null_str, "/wiki/Href_key"));
}
@Test public void Itm_text() { // PURPOSE: only text msg exists; EX: ** Portal:Contents|contents; no href, accesskey, title
fxt.Init__msg__itm("href_key", "main_key", "text", Null_str, Null_str, Null_str); // only define msg for text
fxt.Exec__make("** href_key|main_key");
fxt.Test__objs(fxt.Make__itm("text", Null_str, Null_str, "/wiki/Href_key"));
}
@Test public void Itm_href_absolute() {
fxt.Exec__make("** http://a.org|main_key");
fxt.Test__objs(fxt.Make__itm("main_key", Null_str, Null_str, "http://a.org"));
}
@Test public void Itm_href_manual() {
fxt.Exec__make("** Help:Contents|main_key");
fxt.Test__objs(fxt.Make__itm("main_key", Null_str, Null_str, "/wiki/Help:Contents"));
}
@Test public void Itm_href_xwiki() {
Xop_fxt.Reg_xwiki_alias(fxt.Wiki(), "c", "commons.wikimedia.org");
fxt.Exec__make("** c:Help:Contents|main_key");
fxt.Test__objs(fxt.Make__itm("main_key", Null_str, Null_str, "/site/commons.wikimedia.org/wiki/Help:Contents"));
}
@Test public void Itm_err_missing_key() {
fxt.Exec__make("** no_main_key");
fxt.Test__objs();
}
@Test public void Itm_ignore() { // PURPOSE: ignore SEARCH, TOOLBOX, LANGUAGES
fxt.Exec__make
( "** SEARCH"
, "** TOOLBOX"
, "** LANGUAGES"
);
fxt.Test__objs();
}
@Test public void Itm_comment() { // PURPOSE: ignore comment; EX:de.v:MediaWiki:Sidebar; DATE:2014-03-08
fxt.Init__msg__itm("href_key", "main_key", "text", "title", "accesskey", "href");
fxt.Exec__make("** href_key<!--a-->|main_key<!--b-->");
fxt.Test__objs(fxt.Make__itm("text", "title", "accesskey", "/wiki/Href"));
}
@Test public void Smoke() {
fxt.Init__msg__grp("navigation", "Grp_0_text", "Grp_0_title");
fxt.Init__msg__itm("mainpage", "mainpage-description", "Itm_0_text", "Itm_0_title [a]", "a", "Itm_0_href");
fxt.Init__msg__itm("Portal:Contents", "contents", "Itm_1_text", Null_str, Null_str, Null_str);
fxt.Exec__make
( "* navigation"
, "** mainpage|mainpage-description"
, "** Portal:Contents|contents"
, "* SEARCH"
, "* interaction"
, "** helppage|help"
, "* TOOLBOX"
, "** TOOLBOXEND"
, "* LANGUAGES"
);
fxt.Test__objs
( fxt.Make__grp("Grp_0_text", "Grp_0_title").Subs__add
( fxt.Make__itm("Itm_0_text", "Itm_0_title [a]", "a", "/wiki/Itm_0_href")
, fxt.Make__itm("Itm_1_text", Null_str, Null_str, "/wiki/Portal:Contents")
)
, fxt.Make__grp("interaction", Null_str).Subs__add
( fxt.Make__itm("help", Null_str, Null_str, "/wiki/Helppage")
));
fxt.Test__html
( "<div class=\"portal\" id=\"n-navigation\">"
, " <h3>Grp_0_text</h3>"
, " <div class=\"body\">"
, " <ul>"
, " <li id=\"n-mainpage-description\"><a href=\"/wiki/Itm_0_href\" accesskey=\"a\" title=\"Itm_0_title [a] [a]\">Itm_0_text</a></li>"
, " <li id=\"n-contents\"><a href=\"/wiki/Portal:Contents\" title=\"\">Itm_1_text</a></li>"
, " </ul>"
, " </div>"
, "</div>"
, "<div class=\"portal\" id=\"n-interaction\">"
, " <h3>interaction</h3>"
, " <div class=\"body\">"
, " <ul>"
, " <li id=\"n-help\"><a href=\"/wiki/Helppage\" title=\"\">help</a></li>"
, " </ul>"
, " </div>"
, "</div>"
);
}
@Test public void Itm_template_msg() {
fxt.Init__msg__itm("href", "main", null, null, null, "{{ns:Special}}:Random");
fxt.Exec__make("** href|main");
fxt.Test__objs(fxt.Make__itm("main", Null_str, Null_str, "/wiki/Special:Random"));
}
@Test public void Itm_template_key() {
fxt.Exec__make("** {{ns:Special}}:Random|main");
fxt.Test__objs(fxt.Make__itm("main", Null_str, Null_str, "/wiki/Special:Random"));
}
@Test public void Popups() {
fxt.Init__popups_enabled(true);
fxt.Exec__make
( "* navigation"
, "** mainpage|mainpage-description"
);
fxt.Test__objs
( fxt.Make__grp("navigation", "").Subs__add
( fxt.Make__itm("mainpage-description", Null_str, Null_str, "/wiki/Mainpage")
));
fxt.Test__html
( "<div class=\"portal\" id=\"n-navigation\">"
, " <h3>navigation</h3>"
, " <div class=\"body\">"
, " <ul>"
, " <li id=\"n-mainpage-description\"><a href=\"/wiki/Mainpage\" class='xowa-hover-off' title=\"\">mainpage-description</a></li>"
, " </ul>"
, " </div>"
, "</div>"
);
}
private static final String Null_str = "";
}
class Xoh_sidebar_mgr_fxt {
private Xoae_app app; private Xowe_wiki wiki; private Xoh_sidebar_mgr sidebar_mgr; private Bry_bfr bfr;
public Xoh_sidebar_mgr_fxt Clear() {
app = Xoa_app_fxt.Make__app__edit();
wiki = Xoa_app_fxt.Make__wiki__edit(app);
sidebar_mgr = wiki.Html_mgr().Portal_mgr().Sidebar_mgr();
bfr = Bry_bfr_.Reset(Io_mgr.Len_kb);
Init__popups_enabled(false);
return this;
}
public Xowe_wiki Wiki() {return wiki;}
public Xoh_sidebar_itm Make__grp(String text, String title, Xoh_sidebar_itm... itms) {
Xoh_sidebar_itm rv = new Xoh_sidebar_itm(Bool_.N, Bry_.new_a7(text), Bry_.new_a7(text), null);
rv.Init_by_title_and_accesskey(Bry_.new_a7(title), null, null);
return rv;
}
public Xoh_sidebar_itm Make__itm(String text, String title, String accesskey, String href) {
Xoh_sidebar_itm rv = new Xoh_sidebar_itm(Bool_.Y, Bry_.new_a7(text), Bry_.new_a7(text), Bry_.new_a7(href));
rv.Init_by_title_and_accesskey(Bry_.new_a7(title), Bry_.new_a7(accesskey), null);
return rv;
}
public Xoh_sidebar_mgr_fxt Init__popups_enabled(boolean v) {app.Api_root().Html().Modules().Popups().Enabled_(v); return this;}
public Xoh_sidebar_mgr_fxt Init__msg__grp(String key, String text, String title) {
Init_msg(key, text);
Init_msg("tooltip-n-" + key, title);
return this;
}
public Xoh_sidebar_mgr_fxt Init__msg__itm(String href_key, String main_key, String text, String title, String accesskey, String href) {
if (text != null) Init_msg(main_key, text);
if (href != null) Init_msg(href_key, href);
if (title != null) Init_msg("tooltip-n-" + main_key, title);
if (accesskey != null) Init_msg("accesskey-n-" + main_key, accesskey);
return this;
}
public Xoh_sidebar_mgr_fxt Init_msg(String key, String val) {
Xol_msg_mgr msg_mgr = wiki.Lang().Msg_mgr();
Xol_msg_itm msg_itm = msg_mgr.Itm_by_key_or_new(Bry_.new_a7(key));
msg_itm.Atrs_set(Bry_.new_a7(val), false, String_.Has(val, "{{"));
return this;
}
public void Exec__make(String... raw) {
sidebar_mgr.Make(bfr, Bry_.new_u8(String_.Concat_lines_nl_skip_last(raw)));
}
public void Test__objs(Xoh_sidebar_itm... expd) {
Tfds.Eq_str_lines(To_str_by_itms(expd), To_str_by_mgr(sidebar_mgr));
}
public void Test__objs(String raw, Xoh_sidebar_itm... expd) {
Tfds.Eq_str_lines(To_str_by_itms(expd), To_str_by_mgr(sidebar_mgr));
}
public void Test__html(String... expd) {
Tfds.Eq_str_lines(String_.Concat_lines_nl_skip_last(expd), String_.new_u8(sidebar_mgr.Html_bry()));
}
private static String To_str_by_mgr(Xoh_sidebar_mgr mgr) {
List_adp grps = mgr.Grps();
int len = grps.Len();
Xoh_sidebar_itm[] ary = new Xoh_sidebar_itm[len];
for (int i = 0; i < len; i++)
ary[i] = (Xoh_sidebar_itm)grps.Get_at(i);
return To_str_by_itms(ary);
}
private static String To_str_by_itms(Xoh_sidebar_itm[] ary) {
Bry_bfr bfr = Bry_bfr_.New();
int ary_len = ary.length;
for (int i = 0; i < ary_len; i++)
To_str_by_itm(bfr, ary[i]);
return bfr.To_str_and_clear();
}
private static void To_str_by_itm(Bry_bfr bfr, Xoh_sidebar_itm cur) {
boolean tid_is_itm = cur.Tid_is_itm();
bfr.Add_str_a7(tid_is_itm ? "itm|" : "grp|");
bfr.Add(cur.Text()).Add_byte_pipe();
bfr.Add(cur.Title()).Add_byte_pipe();
if (tid_is_itm) {
bfr.Add(cur.Accesskey()).Add_byte_pipe();
bfr.Add(cur.Href()).Add_byte_pipe();
}
bfr.Add_byte_nl();
int len = cur.Subs__len();
for (int i = 0; i< len; ++i)
To_str_by_itm(bfr, cur.Subs__get_at(i));
}
}

@ -0,0 +1,113 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.htmls.sidebars; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.htmls.*;
import gplx.core.btries.*;
import gplx.langs.htmls.encoders.*;
import gplx.xowa.parsers.lnkis.*;
class Xoh_sidebar_parser { // TS:
public static void Parse(Bry_bfr tmp_bfr, Xowe_wiki wiki, List_adp grps, byte[] src) {
// split MediaWiki:Sidebar into lines
byte[][] lines = Bry_split_.Split(src, Byte_ascii.Nl);
// init
Xop_link_parser link_parser = new Xop_link_parser();
Xoa_url tmp_url = Xoa_url.blank();
Xoh_sidebar_itm cur_grp = null;
// loop lines
int lines_len = lines.length;
for (int i = 0; i < lines_len; i++) {
byte[] line = lines[i];
int line_len = line.length;
if (line_len == 0) continue; // skip blank lines
if (line[0] != Byte_ascii.Star) continue; // skip non-list items; note that all items must begin with "*"
// if **, then itm; else * is grp
boolean tid_is_itm = line[1] == Byte_ascii.Star;
// trim ws; note that tid indicates # of asterisks; EX: '** a' -> 'a'
byte[] raw = Bry_.Trim(line, tid_is_itm ? 2 : 1, line_len);
// strip comments; DATE:2014-03-08
raw = gplx.langs.htmls.Gfh_utl.Del_comments(tmp_bfr, raw);
Xoh_sidebar_itm cur_itm = null;
// parse itm
if (tid_is_itm) {
cur_itm = Parse_itm_or_null(wiki, raw, link_parser, tmp_url, tmp_bfr); if (cur_itm == null) continue;
if (cur_grp == null) // handle null_ref; should only occur for tests
grps.Add(cur_itm);
else
cur_grp.Subs__add(cur_itm);
}
// parse grp
else {
cur_itm = Parse_grp_or_null(wiki, raw); if (cur_itm == null) continue;
cur_grp = cur_itm;
grps.Add(cur_grp);
}
wiki.Msg_mgr().Val_html_accesskey_and_title(cur_itm.Id(), tmp_bfr, cur_itm);
}
}
private static Xoh_sidebar_itm Parse_grp_or_null(Xowe_wiki wiki, byte[] raw) {
// ignore SEARCH, TOOLBOX, LANGUAGES
if (ignore_trie.Match_bgn(raw, 0, raw.length) != null) return null;
byte[] text_key = raw;
byte[] text_val = Resolve_key(wiki, text_key);
return new Xoh_sidebar_itm(Bool_.N, text_key, text_val, null);
}
private static Xoh_sidebar_itm Parse_itm_or_null(Xowe_wiki wiki, byte[] raw, Xop_link_parser link_parser, Xoa_url tmp_url, Bry_bfr bfr) {
// separate into key|val; note that grp uses entire raw for key while itm uses raw after "|"
int pipe_pos = Bry_find_.Find_fwd(raw, Byte_ascii.Pipe);
// if no pipe, warn and return; EX: should be "href|main", but only "href"
if (pipe_pos == Bry_find_.Not_found) {
// don't bother warning if es.wikisource.org and special:Random/Pagina; occurs in 2014-02-03 dump and still present as of 2016-09; note this sidebar item does not show on WMF either
if (Bry_.Eq(wiki.Domain_bry(), Ignore_wiki_ess) && Bry_.Eq(raw, Ignore_item_ess_random)) {}
else
wiki.Appe().Usr_dlg().Warn_many("", "", "sidebar item is missing pipe; only href is available; item will be hidden: item=~{0}", String_.new_u8(raw));
return null;
}
// get text
byte[] text_key = Bry_.Mid(raw, pipe_pos + 1, raw.length);
byte[] text_val = Resolve_key(wiki, text_key);
// get href
byte[] href_key = Bry_.Mid(raw, 0, pipe_pos);
byte[] href_val = Resolve_key(wiki, href_key);
href_val = link_parser.Parse(bfr, tmp_url, wiki, href_val, Bry_.Empty);
return new Xoh_sidebar_itm(Bool_.Y, text_key, text_val, href_val);
}
private static byte[] Resolve_key(Xowe_wiki wiki, byte[] key) {
byte[] val = wiki.Msg_mgr().Val_by_key_obj(key);
if (Bry_.Len_eq_0(val)) val = key; // if key is not found, default to val
return wiki.Parser_mgr().Main().Expand_tmpl(val);
}
private static byte[] Ignore_wiki_ess = Bry_.new_a7("es.wikisource.org"), Ignore_item_ess_random = Bry_.new_u8("special:Random/Página djvu");
private static final byte Ignore__search = 1, Ignore__toolbox = 2, Ignore__toolbox_end = 3, Ignore__languages = 4;
private static final Btrie_slim_mgr ignore_trie = Btrie_slim_mgr.ci_a7()
.Add_str_byte("SEARCH" , Ignore__search)
.Add_str_byte("TOOLBOX" , Ignore__toolbox)
.Add_str_byte("TOOLBOXEND" , Ignore__toolbox_end)
.Add_str_byte("LANGUAGES" , Ignore__languages)
;
}

@ -15,13 +15,11 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.wikis.ctgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.wikis.*;
package gplx.xowa.addons.wikis.ctgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*;
import gplx.xowa.addons.wikis.ctgs.htmls.*;
public class Xoa_ctg_mgr implements Gfo_invk {
public void Init_by_app(Xoae_app app) {
pagectgs_wtr = new Xoctg_pagelist_wtr().Init_by_app(app);
}
public void Init_by_app(Xoae_app app) {}
public boolean Pagecats_grouping_enabled() {return pagecats_grouping_enabled;} private boolean pagecats_grouping_enabled = false;
public Xoctg_pagelist_wtr Pagectgs_wtr() {return pagectgs_wtr;} private Xoctg_pagelist_wtr pagectgs_wtr;
public byte Missing_ctg_cls_tid() {return missing_ctg_cls_tid;} private byte missing_ctg_cls_tid = Missing_ctg_cls_red_tid;
public byte[] Missing_ctg_cls_css() {
switch (missing_ctg_cls_tid) {
@ -60,7 +58,7 @@ public class Xoa_ctg_mgr implements Gfo_invk {
}
}
public static final byte Version_null = Byte_.Zero, Version_1 = 1, Version_2 = 2;
public static final byte Tid_null = Byte_.Max_value_127, Tid_subc = 0, Tid_file = 1, Tid_page = 2, Tid__max = 3;
public static final byte Tid_null = Byte_.Max_value_127, Tid_subc = 0, Tid_file = 1, Tid_page = 2, Tid__max = 3; // SERIALIZED
public static final byte Hidden_n = Byte_.Zero, Hidden_y = (byte)1;
public static final String Html__cls__str = "CategoryTreeLabel CategoryTreeLabelNs14 CategoryTreeLabelCategory";
public static final byte[] Html__cls__bry = Bry_.new_a7(Html__cls__str);

@ -17,6 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*;
import gplx.xowa.wikis.data.tbls.*;
import gplx.xowa.addons.wikis.ctgs.dbs.*;
public class Xoax_ctg_addon implements Xoax_addon_itm { // TODO_OLD:mem_mgr
private final Xow_wiki wiki;
private final Hash_adp_bry hash = Hash_adp_bry.cs();
@ -25,7 +26,7 @@ public class Xoax_ctg_addon implements Xoax_addon_itm { // TODO_OLD:mem_mgr
public Xoctg_ctg_itm Itms__load(byte[] key) {
Xowd_page_itm tmp_page = new Xowd_page_itm();
wiki.Data__core_mgr().Tbl__page().Select_by_ttl(tmp_page, wiki.Ns_mgr().Ns_category(), key);
gplx.xowa.wikis.data.tbls.Xowd_category_itm itm = wiki.Data__core_mgr().Db__cat_core().Tbl__cat_core().Select(tmp_page.Id());
gplx.xowa.wikis.data.tbls.Xowd_category_itm itm = Xodb_cat_db_.Get_cat_core_or_fail(wiki.Data__core_mgr()).Select(tmp_page.Id());
return Itms__add(key, itm.Count_pages(), itm.Count_subcs(), itm.Count_files());
}
public Xoctg_ctg_itm Itms__add(byte[] key, int pages, int subcs, int files) { // TEST:

@ -15,10 +15,9 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.wikis.ctgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.wikis.*;
package gplx.xowa.addons.wikis.ctgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*;
public class Xoctg_page_xtn {
public Xoctg_page_xtn(byte tid, byte[] sortkey) {this.tid = tid; this.sortkey = sortkey;}
public byte[] Sortkey() {return sortkey;} public void Sortkey_(byte[] v) {this.sortkey = v;} private byte[] sortkey;
public byte Tid() {return tid;} public void Tid_(byte v) {this.tid = v;} private byte tid;
public byte Hidden() {return hidden;} public void Hidden_(byte v) {hidden = v;} private byte hidden = Bool_.__byte;
public byte Tid() {return tid;} private final byte tid;
public byte[] Sortkey() {return sortkey;} private final byte[] sortkey;
}

@ -15,12 +15,15 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.wikis.ctgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.wikis.*;
import gplx.xowa.langs.*; import gplx.xowa.htmls.core.htmls.*;
interface Xoctg_fmtr_itm extends gplx.core.brys.Bfr_arg {
int Grp_end_idx();
boolean Grp_end_at_col();
int Col_idx(); void Col_idx_(int col_idx, int col_bgn);
void Init_from_all(Xowe_wiki wiki, Xol_lang_itm lang, Xoh_wtr_ctx hctx, Xoctg_view_ctg ctg, Xoctg_fmtr_all mgr, Xoctg_view_grp itms_list, int itms_list_len);
void Init_from_grp(byte[] grp_ttl, int i);
package gplx.xowa.addons.wikis.ctgs.bldrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*;
import gplx.xowa.bldrs.wkrs.*;
public class Xoax_ctg_bldr_addon implements Xoax_addon_itm, Xoax_addon_itm__bldr {
public Xob_cmd[] Bldr_cmds() {
return new Xob_cmd[]
{ gplx.xowa.addons.wikis.ctgs.bldrs.Xob_pageprop_cmd.Prototype
, gplx.xowa.addons.wikis.ctgs.bldrs.Xob_catlink_cmd.Prototype
};
}
public String Addon__key() {return "xowa.builds.ctgs";}
}

@ -0,0 +1,56 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.bldrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*;
import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.wkrs.*; import gplx.xowa.bldrs.sqls.*;
public class Xob_catlink_cmd extends Xob_sql_dump_base implements Sql_file_parser_cmd {
private final Xob_catlink_mgr mgr = new Xob_catlink_mgr();
private int tmp_page_id;
private byte[] tmp_ctg_ttl, tmp_sortkey, tmp_timestamp, tmp_sortkey_prefix, tmp_collation, tmp_type;
public Xob_catlink_cmd(Xob_bldr bldr, Xowe_wiki wiki) {this.Cmd_ctor(bldr, wiki);}
@Override public String Sql_file_name() {return Dump_file_name;} public static final String Dump_file_name = "categorylinks";
@Override public void Cmd_bgn_hook(Xob_bldr bldr, Sql_file_parser parser) {
wiki.Init_assert();
parser.Save_csv_n_().Fld_cmd_(this).Flds_req_idx_(7, 0, 1, 2, 3, 4, 5, 6);
mgr.On_cmd_bgn(wiki);
}
@Override public void Cmd_end() {
mgr.On_cmd_end();
this.Cmd_cleanup_sql();
}
public void Exec(byte[] src, byte[] fld_key, int fld_idx, int fld_bgn, int fld_end, Bry_bfr file_bfr, Sql_file_parser_data data) {
switch (fld_idx) {
case Fld__cl_from: this.tmp_page_id = Bry_.To_int_or(src, fld_bgn, fld_end, -1); break;
case Fld__cl_to: this.tmp_ctg_ttl = Bry_.Mid(src, fld_bgn, fld_end); break;
case Fld__cl_sortkey: this.tmp_sortkey = Bry_.Mid(src, fld_bgn, fld_end); break;
case Fld__cl_timestamp: this.tmp_timestamp = Bry_.Mid(src, fld_bgn, fld_end); break;
case Fld__cl_sortkey_prefix: this.tmp_sortkey_prefix = Bry_.Mid(src, fld_bgn, fld_end); break;
case Fld__cl_collation: this.tmp_collation = Bry_.Mid(src, fld_bgn, fld_end); break;
case Fld__cl_type: this.tmp_type = Bry_.Mid(src, fld_bgn, fld_end);
mgr.On_cmd_row(tmp_page_id, tmp_ctg_ttl, tmp_sortkey, tmp_timestamp, tmp_sortkey_prefix, tmp_collation, tmp_type);
break;
}
}
private static final byte Fld__cl_from = 0, Fld__cl_to = 1, Fld__cl_sortkey = 2, Fld__cl_timestamp = 3, Fld__cl_sortkey_prefix = 4, Fld__cl_collation = 5, Fld__cl_type = 6;
public static final String BLDR_CMD_KEY = "wiki.categorylinks";
@Override public String Cmd_key() {return BLDR_CMD_KEY;}
public static final Xob_cmd Prototype = new Xob_catlink_cmd(null, null);
@Override public Xob_cmd Cmd_clone(Xob_bldr bldr, Xowe_wiki wiki) {return new Xob_catlink_cmd(bldr, wiki);}
}

@ -0,0 +1,91 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.bldrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*;
import gplx.dbs.*; import gplx.xowa.addons.wikis.ctgs.dbs.*;
import gplx.xowa.addons.wikis.ctgs.enums.*;
import gplx.xowa.wikis.data.*; import gplx.xowa.wikis.data.tbls.*;
import gplx.xowa.addons.wikis.ctgs.bldrs.ucas.*;
class Xob_catlink_mgr {
private Xowe_wiki wiki;
private Xodb_tmp_cat_db tmp_db; private Db_conn tmp_conn; private Xodb_tmp_cat_link_tbl tmp_link_tbl;
private final Xoctg_collation_enum collation_enum = new Xoctg_collation_enum(); private final Xoctg_type_enum type_enum = new Xoctg_type_enum();
private Uca_trie trie; private final Bry_bfr uca_bfr = Bry_bfr_.New();
private int rows = 0;
public void On_cmd_bgn(Xowe_wiki wiki) {
this.wiki = wiki;
// init tmp_db, tmp_link_tbl
this.tmp_db = new Xodb_tmp_cat_db(wiki);
this.tmp_conn = tmp_db.Conn();
this.tmp_link_tbl = new Xodb_tmp_cat_link_tbl(tmp_conn);
tmp_link_tbl.Insert_bgn();
}
public void On_cmd_row(int page_id, byte[] ctg_ttl, byte[] sortkey_orig, byte[] timestamp_bry, byte[] sortkey_prefix, byte[] collation_bry, byte[] type_bry) {
// convert strings to numbers
long timestamp = DateAdp_.parse_fmt(String_.new_u8(timestamp_bry), "YYYY-MM-dd HH:mm:ss").Timestamp_unix();
byte collation_id = collation_enum.To_tid_or_fail(collation_bry);
byte type_id = type_enum.To_tid_or_fail(type_bry);
// sortkey; handle \n
byte[] sortkey_actl = sortkey_orig;
int nl_pos = Bry_find_.Find_fwd(sortkey_actl, Byte_ascii.Nl);
if (nl_pos != Bry_find_.Not_found) // some sortkeys have format of "sortkey\ntitle"; discard 2nd to conserve hard-disk space; EX: "WALES, JIMMY\nJIMMY WALES"
sortkey_actl = Bry_.Mid(sortkey_actl, 0, nl_pos); // NOTE: some sortkeys have space which will sort under " "; EX: ' \nART' -> " "; SEE: s.w:Category:Art
// sortkey; handle uca
if (collation_id == Xoctg_collation_enum.Tid__uca) {
if (trie == null) trie = new Uca_trie();
trie.Decode(uca_bfr, sortkey_actl, 0, sortkey_actl.length);
sortkey_actl = uca_bfr.Len() == 0 ? Byte_ascii.Space_bry : uca_bfr.To_bry_and_clear();
}
// insert to tmp; notify; commit
tmp_link_tbl.Insert_cmd_by_batch(page_id, ctg_ttl, sortkey_actl, timestamp, sortkey_prefix, collation_id, type_id);
if (++rows % 100000 == 0) {
Gfo_usr_dlg_.Instance.Prog_many("", "", "parsing categorylinks sql: ~{0}", Int_.To_str_fmt(rows, "#,##0"));
tmp_conn.Txn_sav();
}
}
public void On_cmd_end() {
tmp_link_tbl.Insert_end();
// create cat_sort
tmp_link_tbl.Create_idx__sortkey(); // index should make SELECT DISTINCT faster
Db_conn cat_core_conn = wiki.Data__core_mgr().Props().Layout_text().Tid_is_lot()
? wiki.Data__core_mgr().Dbs__make_by_tid(Xow_db_file_.Tid__cat_core).Conn()
: wiki.Data__core_mgr().Db__core().Conn();
Xodb_cat_sort_tbl cat_sort_tbl = new Xodb_cat_sort_tbl(cat_core_conn);
cat_core_conn.Meta_tbl_remake(cat_sort_tbl);
cat_sort_tbl.Insert_by_select(tmp_conn);
// make catlink_dbs
cat_sort_tbl.Create_idx__key(); // index will be needed for join
tmp_link_tbl.Create_idx__to_ttl(); // index will be needed for join
Db_conn page_conn = wiki.Data__core_mgr().Db__core().Conn();
Xob_catlink_wkr wkr = new Xob_catlink_wkr();
wkr.Make_catlink_dbs(wiki, tmp_conn, page_conn, cat_core_conn);
// make catcore_tbl; update page!cat_db_id
wkr.Make_catcore_tbl(wiki, tmp_conn, page_conn, cat_core_conn);
wkr.Update_page_cat_db_id(wiki, page_conn);
// cleanup
cat_sort_tbl.Delete_idx__key(); // remove idx
tmp_db.Delete();
}
}

@ -0,0 +1,140 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.bldrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*;
import gplx.dbs.*;
import gplx.xowa.wikis.data.*; import gplx.xowa.wikis.data.tbls.*; import gplx.xowa.addons.wikis.ctgs.dbs.*;
class Xob_catlink_wkr {
public void Make_catlink_dbs(Xowe_wiki wiki, Db_conn tmp_conn, Db_conn page_conn, Db_conn cat_core_conn) {
// init select
Db_attach_mgr attach_mgr = new Db_attach_mgr(page_conn, new Db_attach_itm("temp_db", tmp_conn), new Db_attach_itm("cat_db", cat_core_conn)); // NOTE: main_conn must be page_conn, else sqlite will be very slow when doing insert
String sql = attach_mgr.Resolve_sql(String_.Concat_lines_nl_skip_last
( "SELECT tcl.cl_from"
, ", p.page_id"
, ", tcl.cl_type_id"
, ", cs.cs_id"
, ", tcl.cl_timestamp"
, "FROM <temp_db>tmp_cat_link tcl"
, " JOIN <cat_db>cat_sort cs ON tcl.cl_sortkey = cs.cs_key"
, " JOIN page p ON p.page_namespace = 14 AND tcl.cl_to_ttl = p.page_title"
, "ORDER BY 1" // NOTE: must sort by page_id to keep all cats for page in one db
));
attach_mgr.Attach();
// select from tmp_db and insert insert into cat_link
Xodb_cat_link_tbl cat_link_tbl = Make_cat_link_tbl(wiki, null);
Db_rdr rdr = attach_mgr.Conn_main().Stmt_sql(sql).Exec_select__rls_auto();
try {
// misc row vals
long db_size_cur = 0, db_size_max = wiki.Appe().Api_root().Bldr().Wiki().Import().Cat_link_db_max();
int page_id_prv = -1;
int rows = 0;
while (rdr.Move_next()) {
// check if row can fit in db; else update db_size
int page_id_cur = rdr.Read_int("cl_from");
long db_size_new = db_size_cur + 46;// 46 = 3 ints (12) + 1 long (8) + 1 byte (2?) + 2 index (24?) + 9 fudge factor (?); DATE:2016-09-06
if ( db_size_cur > db_size_max // size exceeded
&& page_id_cur != page_id_prv) { // and page_id is diff; keeps all page_ids in one db
cat_link_tbl = Make_cat_link_tbl(wiki, cat_link_tbl);
db_size_new = 0;
}
db_size_cur = db_size_new;
page_id_prv = page_id_cur;
// insert; notify;
cat_link_tbl.Insert_cmd_by_batch(page_id_prv, rdr.Read_int("page_id"), rdr.Read_byte("cl_type_id"), rdr.Read_int("cs_id"), rdr.Read_long("cl_timestamp"));
if (++rows % 100000 == 0)
Gfo_usr_dlg_.Instance.Prog_many("", "", "inserting cat_link row: ~{0}", Int_.To_str_fmt(rows, "#,##0"));
}
}
finally {rdr.Rls();}
Term_cat_link_tbl(cat_link_tbl);
attach_mgr.Detach(); // NOTE: must detach after txn
}
private static Xodb_cat_link_tbl Make_cat_link_tbl(Xowe_wiki wiki, Xodb_cat_link_tbl cat_link_tbl) {
Term_cat_link_tbl(cat_link_tbl);
// get cat_link_conn
Db_conn cat_link_conn = wiki.Data__core_mgr().Props().Layout_text().Tid_is_lot()
? wiki.Data__core_mgr().Dbs__make_by_tid(Xow_db_file_.Tid__cat_link).Conn()
: wiki.Data__core_mgr().Db__core().Conn();
// make tbl
Xodb_cat_link_tbl rv = new Xodb_cat_link_tbl(cat_link_conn);
cat_link_conn.Meta_tbl_remake(rv);
rv.Insert_bgn();
return rv;
}
private static void Term_cat_link_tbl(Xodb_cat_link_tbl cat_link_tbl) {
if (cat_link_tbl == null) return;
cat_link_tbl.Insert_end();
cat_link_tbl.Create_idx__from();
cat_link_tbl.Create_idx__to_id();
}
public void Make_catcore_tbl(Xowe_wiki wiki, Db_conn tmp_conn, Db_conn page_conn, Db_conn cat_core_conn) {
Db_attach_mgr attach_mgr = new Db_attach_mgr(cat_core_conn, new Db_attach_itm("temp_db", tmp_conn), new Db_attach_itm("page_db", page_conn));
Xowd_cat_core_tbl cat_core_tbl = new Xowd_cat_core_tbl(cat_core_conn, Bool_.N);
cat_core_conn.Meta_tbl_remake(cat_core_tbl);
String sql = String_.Concat_lines_nl_skip_last // ANSI.Y
( "INSERT INTO cat_core (cat_id, cat_pages, cat_subcats, cat_files, cat_hidden, cat_link_db_id)"
, "SELECT p.page_id"
, ", Sum(CASE WHEN tcl.cl_type_id = 2 THEN 1 ELSE 0 END)"
, ", Sum(CASE WHEN tcl.cl_type_id = 0 THEN 1 ELSE 0 END)"
, ", Sum(CASE WHEN tcl.cl_type_id = 1 THEN 1 ELSE 0 END)"
, ", CASE WHEN h.cat_id IS NULL THEN 0 ELSE 1 END"
, ", -1"
, "FROM <temp_db>tmp_cat_link tcl"
, " JOIN <page_db>page p ON p.page_namespace = 14 AND tcl.cl_to_ttl = p.page_title"
, " LEFT JOIN <temp_db>tmp_cat_hidden h ON h.cat_id = p.page_id"
, "GROUP BY p.page_id"
);
attach_mgr.Exec_sql(sql);
}
public void Update_page_cat_db_id(Xowe_wiki wiki, Db_conn page_conn) {
// assert page_cat_db_id exists
Xow_db_mgr db_mgr = wiki.Data__core_mgr();
Xowd_page_tbl page_tbl = db_mgr.Db__core().Tbl__page();
page_conn.Meta_fld_append_if_missing(page_tbl.Tbl_name(), page_tbl.Flds__all(), Dbmeta_fld_itm.new_int("page_cat_db_id").Default_(-1));
// prep sql
String sql = String_.Concat_lines_nl_skip_last
( "UPDATE page"
, "SET page_cat_db_id = {0}"
, "WHERE page_id IN (SELECT cl_from FROM <link_db>cat_link WHERE cl_from = page.page_id);"
);
Db_attach_mgr attach_mgr = new Db_attach_mgr(page_conn);
// loop cat_link dbs and update page_id
boolean layout_is_lot = wiki.Data__core_mgr().Props().Layout_text().Tid_is_lot();
int len = db_mgr.Dbs__len();
for (int i = 0; i < len; ++i) {
Xow_db_file link_db = db_mgr.Dbs__get_at(i);
switch (link_db.Tid()) {
case Xow_db_file_.Tid__core:
if (layout_is_lot) continue; // use core_db is all or few; skip if lot;
break;
case Xow_db_file_.Tid__cat_link:
break;
default:
continue;
}
attach_mgr.Conn_links_(new Db_attach_itm("link_db", link_db.Conn()));
Gfo_usr_dlg_.Instance.Prog_many("", "", "updating page.cat_db_id; db=~{0}", link_db.Id());
attach_mgr.Exec_sql(sql, link_db.Id());
}
}
}

@ -0,0 +1,60 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.bldrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*;
import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.wkrs.*; import gplx.xowa.bldrs.sqls.*;
import gplx.dbs.*; import gplx.xowa.addons.wikis.ctgs.dbs.*;
public class Xob_pageprop_cmd extends Xob_sql_dump_base implements Sql_file_parser_cmd {
private int tmp_id;
private boolean tmp_key_is_hiddencat;
private int rows;
private Xodb_tmp_cat_hidden_tbl tbl;
public Xob_pageprop_cmd(Xob_bldr bldr, Xowe_wiki wiki) {this.Cmd_ctor(bldr, wiki);}
@Override public String Sql_file_name() {return Dump_file_name;} public static final String Dump_file_name = "page_props";
@Override public void Cmd_bgn_hook(Xob_bldr bldr, Sql_file_parser parser) {
wiki.Init_assert();
parser.Save_csv_n_().Fld_cmd_(this).Flds_req_idx_(4, 0, 1, 2); // NOTE: 4 b/c MW added fld_3:pp_sortkey; DATE:2014-04-28
Xodb_tmp_cat_db tmp_db = new Xodb_tmp_cat_db(wiki);
tbl = new Xodb_tmp_cat_hidden_tbl(tmp_db.Conn());
tbl.Insert_bgn();
}
@Override public void Cmd_end() {
tbl.Insert_end();
this.Cmd_cleanup_sql();
}
public void Exec(byte[] src, byte[] fld_key, int fld_idx, int fld_bgn, int fld_end, Bry_bfr file_bfr, Sql_file_parser_data data) {
switch (fld_idx) {
case Fld__id: this.tmp_id = Bry_.To_int_or(src, fld_bgn, fld_end, -1); break;
case Fld__key: this.tmp_key_is_hiddencat = Bry_.Eq(src, fld_bgn, fld_end, Key_hiddencat); break;
case Fld__val:
if (!tmp_key_is_hiddencat) {data.Cancel_row_y_(); return;}
tbl.Insert_cmd_by_batch(tmp_id);
if (++rows % 10000 == 0) usr_dlg.Prog_many("", "", "parsing pageprops sql: row=~{0}", Int_.To_str_fmt(rows, "#,##0"));
break;
}
}
private static final byte Fld__id = 0, Fld__key = 1, Fld__val = 2;
public static final String BLDR_CMD_KEY = "wiki.page_props";
@Override public String Cmd_key() {return BLDR_CMD_KEY;}
public static final Xob_cmd Prototype = new Xob_pageprop_cmd(null, null);
@Override public Xob_cmd Cmd_clone(Xob_bldr bldr, Xowe_wiki wiki) {return new Xob_pageprop_cmd(bldr, wiki);}
private static final byte[] Key_hiddencat = Bry_.new_a7("hiddencat");
}

@ -15,12 +15,12 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.bldrs.cmds.ctgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.cmds.*;
package gplx.xowa.addons.wikis.ctgs.bldrs.ucas; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.bldrs.*;
import gplx.core.btries.*;
class Uca_trie {
public class Uca_trie {
private final Btrie_slim_mgr trie = Btrie_slim_mgr.cs();
private final Btrie_rv trv = new Btrie_rv();
public void Init() {
public Uca_trie() {
Init_itm(1, Bry_.New_by_ints(1,1));
Init_itm(2, Bry_.New_by_ints(1,1));
Init_itm(3, Bry_.New_by_ints(1,1));

@ -15,7 +15,7 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.bldrs.cmds.ctgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.cmds.*;
package gplx.xowa.addons.wikis.ctgs.bldrs.ucas; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.bldrs.*;
import org.junit.*; import gplx.xowa.bldrs.*;
public class Uca_trie_tst {
@Before public void init() {fxt.Clear();} private Xob_base_fxt fxt = new Xob_base_fxt();

@ -15,11 +15,12 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.bldrs.cmds.ctgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.cmds.*;
import gplx.core.ios.*;
import gplx.xowa.bldrs.sqls.*;
public class Xob_categorylinks_txt extends Xob_categorylinks_base {
public Xob_categorylinks_txt(Xob_bldr bldr, Xowe_wiki wiki) {this.Cmd_ctor(bldr, wiki); this.make_fil_len = Io_mgr.Len_mb;}
@Override public String Cmd_key() {return Xob_cmd_keys.Key_tdb_text_cat_link;}
@Override public Io_sort_cmd Make_sort_cmd(Sql_file_parser sql_parser) {return new Io_sort_fil_basic(bldr.Usr_dlg(), this.Make_url_gen(), make_fil_len);}
package gplx.xowa.addons.wikis.ctgs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*;
import gplx.dbs.*; import gplx.xowa.wikis.data.*; import gplx.xowa.wikis.data.tbls.*; import gplx.xowa.wikis.dbs.*;
public class Xodb_cat_db_ {
public static Xowd_cat_core_tbl Get_cat_core_or_fail(Xow_db_mgr db_mgr) {
Xow_db_file cat_core_db = db_mgr.Dbs__get_by_tid_or_core(Xow_db_file_.Tid__cat_core);
Xowd_cat_core_tbl cat_core_tbl = new Xowd_cat_core_tbl(cat_core_db.Conn(), db_mgr.Props().Schema_is_1());
return cat_core_tbl;
}
}

@ -0,0 +1,69 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*;
import gplx.dbs.*;
import gplx.xowa.addons.wikis.ctgs.htmls.pageboxs.*;
public class Xodb_cat_link_tbl implements Db_tbl {
private final Dbmeta_fld_list flds = new Dbmeta_fld_list();
private final String fld_from, fld_to_id, fld_type_id, fld_sortkey_id, fld_timestamp_unix;
private Db_stmt stmt_insert;
public Xodb_cat_link_tbl(Db_conn conn) {
this.conn = conn;
this.tbl_name = "cat_link";
this.fld_from = flds.Add_int ("cl_from");
this.fld_to_id = flds.Add_int ("cl_to_id");
this.fld_type_id = flds.Add_byte ("cl_type_id");
this.fld_sortkey_id = flds.Add_int ("cl_sortkey_id");
this.fld_timestamp_unix = flds.Add_long ("cl_timestamp_unix");
conn.Rls_reg(this);
}
public Db_conn Conn() {return conn;} private final Db_conn conn;
public String Tbl_name() {return tbl_name;} private final String tbl_name;
public void Create_tbl() {conn.Meta_tbl_create(Dbmeta_tbl_itm.New(tbl_name, flds));}
public void Create_idx__from() {conn.Meta_idx_create(Dbmeta_idx_itm.new_normal_by_tbl(tbl_name, fld_from, fld_from));}
public void Create_idx__to_id() {conn.Meta_idx_create(Dbmeta_idx_itm.new_normal_by_tbl(tbl_name, fld_to_id, fld_to_id));}
public void Insert_bgn() {conn.Txn_bgn("cl__insert"); stmt_insert = conn.Stmt_insert(tbl_name, flds);}
public void Insert_end() {conn.Txn_end(); stmt_insert = Db_stmt_.Rls(stmt_insert);}
public void Insert_cmd_by_batch(int from, int to_id, byte type_id, int sortkey_id, long timestamp_unix) {
stmt_insert.Clear()
.Val_int(fld_from , from)
.Val_int(fld_to_id , to_id)
.Val_byte(fld_type_id , type_id)
.Val_int(fld_sortkey_id , sortkey_id)
.Val_long(fld_timestamp_unix , timestamp_unix)
.Exec_insert();
}
public void Rls() {
stmt_insert = Db_stmt_.Rls(stmt_insert);
}
}
/*
NOTE_1: categorylinks row size: 34 + 20 + 12 + (cat_sortkey.length * 2)
row length (data) : 34=8+4+4+14+4 ROWID, cl_from, cl_to_id, cl_timestamp, cl_type_id
cl_main length (idx) : 20=8+4+4+4 ROWID, cl_from, cl_to_id, cl_type_id
cl_from length (idx) : 12=8+4 ROWID, cl_from
variable_data length : cat_sortkey.length * 2 sortkey is used for row and cl_main
Note the following
. ints are 4 bytes
. tinyint is assumed to be 4 bytes (should be 1, but sqlite only has one numeric datatype, so import all 4?)
. varchar(14) is assumed to be 14 bytes (should be 15? +1 for length of varchar?)
. calculations work out "too well". comparing 4 databases gets +/- .25 bytes per row. however
.. - bytes should not be possible
.. +.25 bytes is too low (18 MB out of 5.5 GB).*; there must be other bytes used for page breaks / fragmentation
*/

@ -0,0 +1,44 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*;
import gplx.dbs.*; import gplx.dbs.qrys.*; import gplx.xowa.addons.wikis.ctgs.*;
public class Xodb_cat_sort_tbl implements Db_tbl {
private final Dbmeta_fld_list flds = new Dbmeta_fld_list();
private final String fld_key;
public Xodb_cat_sort_tbl(Db_conn conn) {
this.conn = conn;
this.tbl_name = "cat_sort";
flds.Add_int_pkey_autonum("cs_id");
this.fld_key = flds.Add_str ("cs_key", 255);
conn.Rls_reg(this);
}
public Db_conn Conn() {return conn;} private final Db_conn conn;
public String Tbl_name() {return tbl_name;} private final String tbl_name;
public void Create_tbl() {conn.Meta_tbl_create(Dbmeta_tbl_itm.New(tbl_name, flds));}
public void Create_idx__key() {conn.Meta_idx_create(Dbmeta_idx_itm.new_normal_by_tbl(tbl_name, fld_key, fld_key));}
public void Delete_idx__key() {conn.Meta_idx_delete(tbl_name, fld_key);}
public void Insert_by_select(Db_conn tmp_conn) {
Db_attach_mgr attach_mgr = new Db_attach_mgr(conn, new Db_attach_itm("temp_db", tmp_conn));
attach_mgr.Exec_sql(String_.Concat_lines_nl
( "INSERT INTO cat_sort (cs_key)"
, "SELECT DISTINCT cl_sortkey"
, "FROM <temp_db>tmp_cat_link"
));
}
public void Rls() {}
}

@ -15,12 +15,17 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.bldrs.cmds.texts.tdbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.cmds.*; import gplx.xowa.bldrs.cmds.texts.*;
import gplx.xowa.addons.wikis.searchs.bldrs.*;
public class Xob_search_tdb extends Srch_bldr_wkr_base {
public Xob_search_tdb(Xob_bldr bldr, Xowe_wiki wiki) {this.Cmd_ctor(bldr, wiki);}
@Override public String Page_wkr__key() {return Xob_cmd_keys.Key_tdb_make_search_title;}
@Override public gplx.core.ios.Io_make_cmd Make_cmd_site() {
return new Xob_make_cmd_site(bldr.Usr_dlg(), this.make_dir, this.make_fil_len);
package gplx.xowa.addons.wikis.ctgs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*;
import gplx.dbs.*;
public class Xodb_tmp_cat_db {
private final Io_url url;
public Xodb_tmp_cat_db(Xowe_wiki wiki) {
this.url = wiki.Fsys_mgr().Root_dir().GenSubFil("xowa.temp.category.sqlite3");
this.conn = Db_conn_bldr.Instance.Get_or_autocreate(true, url);
}
public Db_conn Conn() {return conn;} private final Db_conn conn;
public void Delete() {
conn.Rls_conn();
Io_mgr.Instance.DeleteFil(url);
}
}

@ -0,0 +1,44 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*;
import gplx.dbs.*;
public class Xodb_tmp_cat_hidden_tbl implements Db_tbl {
private final Dbmeta_fld_list flds = new Dbmeta_fld_list();
private final String fld_cat_id;
private Db_stmt stmt_insert;
public Xodb_tmp_cat_hidden_tbl(Db_conn conn) {
this.conn = conn;
this.tbl_name = "tmp_cat_hidden";
this.fld_cat_id = flds.Add_int_pkey ("cat_id");
conn.Rls_reg(this);
conn.Meta_tbl_remake(this);
}
public Db_conn Conn() {return conn;} private final Db_conn conn;
public String Tbl_name() {return tbl_name;} private final String tbl_name;
public void Create_tbl() {conn.Meta_tbl_create(Dbmeta_tbl_itm.New(tbl_name, flds));}
public void Insert_bgn() {conn.Txn_bgn("tch__insert"); stmt_insert = conn.Stmt_insert(tbl_name, flds);}
public void Insert_end() {conn.Txn_end(); stmt_insert = Db_stmt_.Rls(stmt_insert);}
public void Insert_cmd_by_batch(int page_id) {
stmt_insert.Clear()
.Val_int(fld_cat_id , page_id)
.Exec_insert();
}
public void Rls() {
stmt_insert = Db_stmt_.Rls(stmt_insert);
}
}

@ -0,0 +1,58 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*;
import gplx.dbs.*; import gplx.dbs.qrys.*; import gplx.xowa.addons.wikis.ctgs.*;
public class Xodb_tmp_cat_link_tbl implements Db_tbl {
private final Dbmeta_fld_list flds = new Dbmeta_fld_list();
private final String fld_from, fld_to_ttl, fld_sortkey, fld_timestamp, fld_sortkey_prefix, fld_collation_id, fld_type_id;
private Db_stmt stmt_insert;
public Xodb_tmp_cat_link_tbl(Db_conn conn) {
this.conn = conn;
this.tbl_name = "tmp_cat_link";
this.fld_from = flds.Add_int ("cl_from");
this.fld_to_ttl = flds.Add_str ("cl_to_ttl", 255);
this.fld_sortkey = flds.Add_str ("cl_sortkey", 230);
this.fld_timestamp = flds.Add_long ("cl_timestamp");
this.fld_sortkey_prefix = flds.Add_str ("cl_sortkey_prefix", 230);
this.fld_collation_id = flds.Add_byte ("cl_collation_id");
this.fld_type_id = flds.Add_byte ("cl_type_id");
conn.Rls_reg(this);
conn.Meta_tbl_remake(this);
}
public Db_conn Conn() {return conn;} private final Db_conn conn;
public String Tbl_name() {return tbl_name;} private final String tbl_name;
public void Create_tbl() {conn.Meta_tbl_create(Dbmeta_tbl_itm.New(tbl_name, flds));}
public void Insert_bgn() {conn.Txn_bgn("tcl__insert"); stmt_insert = conn.Stmt_insert(tbl_name, flds);}
public void Insert_end() {conn.Txn_end(); stmt_insert = Db_stmt_.Rls(stmt_insert);}
public void Insert_cmd_by_batch(int page_id, byte[] ctg_ttl, byte[] sortkey, long timestamp, byte[] sortkey_prefix, byte collation_id, byte type_id) {
stmt_insert.Clear()
.Val_int(fld_from , page_id)
.Val_bry_as_str(fld_to_ttl , ctg_ttl)
.Val_bry_as_str(fld_sortkey , sortkey)
.Val_long(fld_timestamp , timestamp)
.Val_bry_as_str(fld_sortkey_prefix , sortkey_prefix)
.Val_byte(fld_collation_id , collation_id)
.Val_byte(fld_type_id , type_id)
.Exec_insert();
}
public void Create_idx__sortkey() {conn.Meta_idx_create(Dbmeta_idx_itm.new_normal_by_tbl(tbl_name, fld_sortkey, fld_sortkey));}
public void Create_idx__to_ttl() {conn.Meta_idx_create(Dbmeta_idx_itm.new_normal_by_tbl(tbl_name, fld_to_ttl, fld_to_ttl));}
public void Rls() {
stmt_insert = Db_stmt_.Rls(stmt_insert);
}
}

@ -0,0 +1,31 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.enums; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*;
import gplx.core.btries.*;
public class Xoctg_collation_enum {
private final Btrie_rv trv = new Btrie_rv();
private final Btrie_slim_mgr trie = Btrie_slim_mgr.cs()
.Add_str_byte("uppercase" , Tid__uppercase)
.Add_str_byte("uca" , Tid__uca);
public byte To_tid_or_fail(byte[] raw) {
byte tid = trie.Match_byte_or(trv, raw, 0, raw.length, Byte_.Max_value_127);
if (tid == Byte_.Max_value_127) throw Err_.new_unhandled_default(raw);
return tid;
}
public static final byte Tid__uppercase = 1, Tid__uca = 3;
}

@ -0,0 +1,32 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.enums; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*;
import gplx.core.btries.*;
public class Xoctg_type_enum {
private final Btrie_rv trv = new Btrie_rv();
private final Btrie_slim_mgr trie = Btrie_slim_mgr.cs()
.Add_str_byte("subcat" , Tid__subc)
.Add_str_byte("file" , Tid__file)
.Add_str_byte("page" , Tid__page);
public byte To_tid_or_fail(byte[] raw) {
byte tid = trie.Match_byte_or(trv, raw, 0, raw.length, Byte_.Max_value_127);
if (tid == Byte_.Max_value_127) throw Err_.new_unhandled_default(raw);
return tid;
}
public static final byte Tid__subc = 0, Tid__file = 1, Tid__page = 2, Tid_max = 3;
}

@ -0,0 +1,117 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.htmls.catpages; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*;
import gplx.dbs.*; import gplx.xowa.wikis.data.*; import gplx.xowa.wikis.data.tbls.*; import gplx.xowa.addons.wikis.ctgs.dbs.*;
import gplx.xowa.addons.wikis.ctgs.htmls.catpages.doms.*;
class Xoctg_catpage_loader {
public Xoctg_catpage_ctg Load_by_ttl_or_null(Xow_wiki wiki, Xoa_ttl cat_ttl) {
// get cat_id for cat_ttl from page_tbl
Xow_db_mgr db_mgr = wiki.Data__core_mgr();
Xowd_page_tbl page_tbl = db_mgr.Db__core().Tbl__page();
Xowd_page_itm page_itm = page_tbl.Select_by_ttl_as_itm_or_null(cat_ttl);
if (page_itm == null) {
Gfo_usr_dlg_.Instance.Warn_many("", "", "category does not exist in page table; ttl=~{0}", cat_ttl.Full_db());
return null;
}
// get cat_link db from cat_core_tbl
Xowd_cat_core_tbl cat_core_tbl = Xodb_cat_db_.Get_cat_core_or_fail(db_mgr);
int cat_id = page_itm.Id();
Xowd_category_itm cat_core_itm = cat_core_tbl.Select(cat_id);
if (cat_core_itm == Xowd_category_itm.Null) {
Gfo_usr_dlg_.Instance.Warn_many("", "", "category does not exist in cat_core table; ttl=~{0}", cat_ttl.Full_db());
return null;
}
// load itms from cat_link_db
Xoctg_catpage_ctg rv = new Xoctg_catpage_ctg(cat_ttl.Page_txt());
if (cat_core_itm.File_idx() == -1) // new v3: loop over all cat_link dbs
Search_cat_core_tbls_for_cat_id(rv, wiki, db_mgr, page_tbl.Conn(), cat_core_tbl.Conn(), cat_id);
else { // old v2: use cat_link_db
Xow_db_file cat_link_db = db_mgr.Dbs__get_by_id_or_fail(cat_core_itm.File_idx());
Select_by_cat_id(rv, wiki, page_tbl.Conn(), cat_core_tbl.Conn(), cat_link_db.Conn(), cat_id, Sql_for_v2(cat_id));
}
rv.Make_itms();
return rv;
}
private static void Search_cat_core_tbls_for_cat_id(Xoctg_catpage_ctg rv, Xow_wiki wiki, Xow_db_mgr db_mgr, Db_conn page_conn, Db_conn cat_core_conn, int cat_id) {
// loop over each db unless (a) cat_link_db; (b) core_db (if all or few)
int len = db_mgr.Dbs__len();
for (int i = 0; i < len; ++i) {
Xow_db_file db_file = db_mgr.Dbs__get_at(i);
switch (db_file.Tid()) {
case Xow_db_file_.Tid__cat_link: // always use cat_link db
break;
case Xow_db_file_.Tid__core: // only use core if all or few
if (db_mgr.Props().Layout_text().Tid_is_lot())
continue;
else
break;
default: // else ignore all other files
continue;
}
Select_by_cat_id(rv, wiki, page_conn, cat_core_conn, db_file.Conn(), cat_id, Sql_for_v3(cat_id));
}
}
private static void Select_by_cat_id(Xoctg_catpage_ctg rv, Xow_wiki wiki, Db_conn page_conn, Db_conn cat_core_conn, Db_conn cat_link_conn, int cat_id, String sql) {
// prep sql
Db_attach_mgr attach_mgr = new Db_attach_mgr(cat_link_conn, new Db_attach_itm("page_db", page_conn), new Db_attach_itm("cat_core_db", cat_core_conn));
sql = attach_mgr.Resolve_sql(sql);
attach_mgr.Attach();
// run sql and create itms based on cat_link
Db_rdr rdr = Db_rdr_.Empty;
try {
rdr = cat_link_conn.Stmt_sql(sql).Exec_select__rls_auto();
while (rdr.Move_next()) {
Xoa_ttl page_ttl = wiki.Ttl_parse(rdr.Read_int("page_namespace"), rdr.Read_bry_by_str("page_title"));
Xoctg_catpage_itm itm = new Xoctg_catpage_itm(rdr.Read_int("cl_from"), page_ttl, Bry_.new_u8(rdr.Read_str("cl_sortkey")));
rv.Grp_by_tid(rdr.Read_byte("cl_type_id")).Itms__add(itm);
}
}
finally {
rdr.Rls();
attach_mgr.Detach();
}
}
private static String Sql_for_v3(int cat_id) {
return String_.Concat_lines_nl_skip_last // ANSI.Y
( "SELECT cl.cl_from"
, ", cl.cl_type_id"
, ", p.page_namespace"
, ", p.page_title"
, ", cs.cs_key AS cl_sortkey"
, "FROM cat_link cl"
, " JOIN <page_db>page p ON cl.cl_from = p.page_id"
, " JOIN <cat_core_db>cat_sort cs ON cl.cl_sortkey_id = cs.cs_id"
, "WHERE cl.cl_to_id = " + Int_.To_str(cat_id)
);
}
private static String Sql_for_v2(int cat_id) { // NOTE: main difference is cl_sortkey is on cat_link, not in cat_sort
return String_.Concat_lines_nl_skip_last // ANSI.Y
( "SELECT cl.cl_from"
, ", cl.cl_type_id"
, ", p.page_namespace"
, ", p.page_title"
, ", cl.cl_sortkey"
, "FROM cat_link cl"
, " JOIN <page_db>page p ON cl.cl_from = p.page_id"
, "WHERE cl.cl_to_id = " + Int_.To_str(cat_id)
);
}
}

@ -0,0 +1,52 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.htmls.catpages; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*;
import gplx.xowa.wikis.dbs.*; import gplx.xowa.wikis.data.tbls.*;
import gplx.xowa.langs.*; import gplx.xowa.langs.msgs.*; import gplx.xowa.htmls.core.htmls.*;
import gplx.xowa.wikis.nss.*;
import gplx.xowa.addons.wikis.ctgs.htmls.catpages.doms.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.fmts.*;
public class Xoctg_catpage_mgr {
private final Xoctg_catpage_loader loader = new Xoctg_catpage_loader();
private final Xoctg_catpage_url tmp_catpage_url = new Xoctg_catpage_url();
private final Xoctg_fmt_grp fmt_subcs = Xoctg_fmt_grp.New__subc(), fmt_pages = Xoctg_fmt_grp.New__page(), fmt_files = Xoctg_fmt_grp.New__file();
public Xoctg_fmt_grp Fmt(byte tid) { // TEST:
switch (tid) {
case Xoa_ctg_mgr.Tid_subc: return fmt_subcs;
case Xoa_ctg_mgr.Tid_page: return fmt_pages;
case Xoa_ctg_mgr.Tid_file: return fmt_files;
default: throw Err_.new_unhandled(tid);
}
}
public void Write_catpage(Bry_bfr bfr, Xow_wiki wiki, Xoa_page page, Xoh_wtr_ctx hctx) {
try {
// load categories from cat dbs; exit if not found
tmp_catpage_url.Parse(wiki.App().Usr_dlg(), page.Url());
Xoctg_catpage_ctg dom_ctg = loader.Load_by_ttl_or_null(wiki, page.Ttl());
if (dom_ctg == null) return;
// write html
Xol_lang_itm lang = page.Lang();
fmt_subcs.Write_catpage_grp(bfr, wiki, lang, dom_ctg);
fmt_pages.Write_catpage_grp(bfr, wiki, lang, dom_ctg);
fmt_files.Write_catpage_grp(bfr, wiki, lang, dom_ctg);
}
catch (Exception e) {
Xoa_app_.Usr_dlg().Warn_many("", "", "failed to generate category: title=~{0} err=~{1}", page.Url_bry_safe(), Err_.Message_gplx_log(e));
}
}
}

@ -15,17 +15,17 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.wikis.ctgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.wikis.*;
package gplx.xowa.addons.wikis.ctgs.htmls.catpages; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*;
import org.junit.*; import gplx.xowa.htmls.core.htmls.*;
public class Xoctg_html_mgr_tst {
import gplx.xowa.addons.wikis.ctgs.htmls.catpages.doms.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.fmts.*;
public class Xoctg_catpage_mgr_tst {
@Before public void init() {fxt.Clear();} private Xoh_ctg_page_fxt fxt = new Xoh_ctg_page_fxt();
@Test public void Page_itm() {
fxt .Init_itm_page("A1")
.Test_html_page(Xoa_ctg_mgr.Tid_page, Byte_ascii.Ltr_A, "\n <li><a href=\"/wiki/A1\" title=\"A1\">A1</a></li>")
;
fxt .Init_itms__pages("A1")
.Test_html_page(Xoa_ctg_mgr.Tid_page, Byte_ascii.Ltr_A, "\n <li><a href=\"/wiki/A1\" title=\"A1\">A1</a></li>");
}
@Test public void Page_itm_missing() {
fxt .Init_itm_page("A1");
fxt .Init_itms__pages("A1");
fxt .Ctg().Grp_by_tid(Xoa_ctg_mgr.Tid_page).Itms()[0].Missing_y_();
fxt .Test_html_page(Xoa_ctg_mgr.Tid_page, Byte_ascii.Ltr_A, "\n <li class=\"xowa-missing-category-entry\"><span title=\"id not found: #0 might be talk/user page\">A1 (missing)</li>");
}
@ -34,12 +34,12 @@ public class Xoctg_html_mgr_tst {
Xoa_url url = Xoa_url.New(Bry_.new_a7("en.wikipedia.org"), page_bry);
Xoa_ttl ttl = Xoa_ttl.Parse(fxt.Wiki(), page_bry);
fxt.Wiki().Appe().Usere().History_mgr().Add(url, ttl, page_bry);
fxt .Init_itm_page("A_1").Init_ctg_name_("Ctg_1").Init_ctg_pages_(0, 1)
fxt .Init_itms__pages("A_1").Init_grp__pages(0, 1)
.Test_html_all(Xoa_ctg_mgr.Tid_page, String_.Concat_lines_nl_skip_last
( ""
, "<div id=\"mw-pages\">"
, " <h2>Pages in category \"Ctg_1\"</h2>"
, " <p>The following page is in this category, out of 0 total.</p>"
, " <p>This category contains only the following page.</p>"
, " <div lang=\"en\" dir=\"ltr\" class=\"mw-content-ltr\">"
, " <table style=\"width: 100%;\">"
, " <tr style=\"vertical-align: top;\">"
@ -56,12 +56,12 @@ public class Xoctg_html_mgr_tst {
));
}
@Test public void Page_all() {
fxt .Init_itm_page("A1").Init_ctg_name_("Ctg_1").Init_ctg_pages_(0, 1)
fxt .Init_itms__pages("A1").Init_grp__pages(0, 1)
.Test_html_all(Xoa_ctg_mgr.Tid_page, String_.Concat_lines_nl_skip_last
( ""
, "<div id=\"mw-pages\">"
, " <h2>Pages in category \"Ctg_1\"</h2>"
, " <p>The following page is in this category, out of 0 total.</p>"
, " <p>This category contains only the following page.</p>"
, " <div lang=\"en\" dir=\"ltr\" class=\"mw-content-ltr\">"
, " <table style=\"width: 100%;\">"
, " <tr style=\"vertical-align: top;\">"
@ -78,12 +78,12 @@ public class Xoctg_html_mgr_tst {
));
}
@Test public void File_all() {
fxt .Init_itm_file("File:A1.png").Init_ctg_name_("Ctg_1").Init_ctg_files_(0, 1)
fxt .Init_itms__files("File:A1.png").Init_grp__files(0, 1)
.Test_html_all(Xoa_ctg_mgr.Tid_file, String_.Concat_lines_nl_skip_last
( ""
, "<div id=\"mw-category-media\">"
, " <h2>Media in category \"Ctg_1\"</h2>"
, " <p>The following file is in this category, out of 0 total.</p>"
, " <p>This category contains only the following file.</p>"
, " <div lang=\"en\" dir=\"ltr\" class=\"mw-content-ltr\">"
, " <table style=\"width: 100%;\">"
, " <tr style=\"vertical-align: top;\">"
@ -116,12 +116,12 @@ public class Xoctg_html_mgr_tst {
// , " </ul>"
}
@Test public void Subc_all() {
fxt .Init_itm_ctg("Category:Subc_1").Init_ctg_name_("Ctg_1").Init_ctg_files_(0, 1)
fxt .Init_itms__subcs("Category:Subc_1").Init_grp__files(0, 1)
.Test_html_all(Xoa_ctg_mgr.Tid_subc, String_.Concat_lines_nl_skip_last
( ""
, "<div id=\"mw-subcategories\">"
, " <h2>Subcategories</h2>"
, " <p>This category has the following subcategory, out of 0 total.</p>"
, " <p>This category has only the following subcategory.</p>"
, " <div lang=\"en\" dir=\"ltr\" class=\"mw-content-ltr\">"
, " <table style=\"width: 100%;\">"
, " <tr style=\"vertical-align: top;\">"
@ -152,12 +152,12 @@ public class Xoctg_html_mgr_tst {
));
}
@Test public void Page_all_cols() {
fxt .Init_itm_page("A1", "A2", "A3", "B1", "C1").Init_ctg_name_("Ctg_1").Init_ctg_pages_(0, 5)
fxt .Init_itms__pages("A1", "A2", "A3", "B1", "C1").Init_grp__pages(0, 5)
.Test_html_all(Xoa_ctg_mgr.Tid_page, String_.Concat_lines_nl_skip_last
( ""
, "<div id=\"mw-pages\">"
, " <h2>Pages in category \"Ctg_1\"</h2>"
, " <p>The following 5 pages are in this category, out of 0 total.</p>"
, " <p>The following 5 pages are in this category, out of 5 total.</p>"
, " <div lang=\"en\" dir=\"ltr\" class=\"mw-content-ltr\">"
, " <table style=\"width: 100%;\">"
, " <tr style=\"vertical-align: top;\">"
@ -191,12 +191,12 @@ public class Xoctg_html_mgr_tst {
));
}
@Test public void Title__escape_quotes() {// PURPOSE: quotes in title should be escaped; DATE:2015-12-28
fxt .Init_itm_page("A\"1").Init_ctg_name_("Ctg_1").Init_ctg_pages_(0, 1)
fxt .Init_itms__pages("A\"1").Init_grp__pages(0, 1)
.Test_html_all(Xoa_ctg_mgr.Tid_page, String_.Concat_lines_nl_skip_last
( ""
, "<div id=\"mw-pages\">"
, " <h2>Pages in category \"Ctg_1\"</h2>"
, " <p>The following page is in this category, out of 0 total.</p>"
, " <p>This category contains only the following page.</p>"
, " <div lang=\"en\" dir=\"ltr\" class=\"mw-content-ltr\">"
, " <table style=\"width: 100%;\">"
, " <tr style=\"vertical-align: top;\">"
@ -213,7 +213,7 @@ public class Xoctg_html_mgr_tst {
));
}
@Test public void Bld_rslts_lnk() {
fxt.Init_itm_page("A1").Init_ctg_name_("Ctg_1").Init_ctg_pages_(1, 1)
fxt .Init_itms__pages("A1").Init_grp__pages(1, 1)
.Test_bld_rslts_lnk(Bool_.Y, "Category:Ctg_1", String_.Concat_lines_nl
( ""
, " (<a href=\"/wiki/Category:Ctg_1?pageuntil=A1#mw-pages\" class=\"xowa_nav\" title=\"Category:Ctg_1\">previous 0</a>)"
@ -221,24 +221,24 @@ public class Xoctg_html_mgr_tst {
));
}
@Test public void Bld_rslts_lnk__encoded() { // escape quotes and spaces; DATE:2016-01-11
fxt.Init_itm_page("A\" b").Init_ctg_name_("Ctg_1").Init_ctg_pages_(1, 1)
fxt .Init_itms__pages("A\" b").Init_grp__pages(1, 1)
.Test_bld_rslts_lnk(Bool_.Y, "Category:Ctg_1", String_.Concat_lines_nl
( ""
, " (<a href=\"/wiki/Category:Ctg_1?pageuntil=A%22+b#mw-pages\" class=\"xowa_nav\" title=\"Category:Ctg_1\">previous 0</a>)"
, " (<a href=\"/wiki/Category:Ctg_1?pagefrom=A%22+b#mw-pages\" class=\"xowa_nav\" title=\"Category:Ctg_1\">next 0</a>)"
));
}
@Test public void Calc_col_max() {
Tst_calc_col_max(3, 10, 0, 4);
Tst_calc_col_max(3, 10, 1, 3);
Tst_calc_col_max(3, 10, 2, 3);
Tst_calc_col_max(3, 11, 0, 4);
Tst_calc_col_max(3, 11, 1, 4);
Tst_calc_col_max(3, 11, 2, 3);
Tst_calc_col_max(3, 12, 0, 4);
Tst_calc_col_max(3, 12, 1, 4);
Tst_calc_col_max(3, 12, 2, 4);
} public void Tst_calc_col_max(int cols_total, int len, int col_idx, int expd) {Tfds.Eq(expd, Xoctg_fmtr_grp.Calc_col_max(cols_total, len, col_idx));}
@Test public void Calc_col_len() {
fxt.Test__calc_col_len(10, 0, 4); // for 10 items, col 0 has 4 items
fxt.Test__calc_col_len(10, 1, 3); // for 10 items, col 1 has 3 items
fxt.Test__calc_col_len(10, 2, 3); // for 10 items, col 2 has 3 items
fxt.Test__calc_col_len(11, 0, 4);
fxt.Test__calc_col_len(11, 1, 4);
fxt.Test__calc_col_len(11, 2, 3);
fxt.Test__calc_col_len(12, 0, 4);
fxt.Test__calc_col_len(12, 1, 4);
fxt.Test__calc_col_len(12, 2, 4);
}
}
class Xoh_ctg_page_fxt {
public Xoh_ctg_page_fxt Clear() {
@ -246,55 +246,56 @@ class Xoh_ctg_page_fxt {
app = Xoa_app_fxt.Make__app__edit();
wiki = Xoa_app_fxt.Make__wiki__edit(app);
ctg_html = wiki.Html_mgr().Ns_ctg();
ctg = new Xoctg_view_ctg();
}
ctg = new Xoctg_catpage_ctg(Bry_.new_a7("Ctg_1"));
return this;
} private Xoae_app app; private Xoctg_html_mgr ctg_html;
} private Xoae_app app; private Xoctg_catpage_mgr ctg_html;
public void Test__calc_col_len(int grp_len, int col_idx, int expd) {Tfds.Eq(expd, Xoctg_fmt_itm_base.Calc_col_len(grp_len, col_idx, 3));}
public Xowe_wiki Wiki() {return wiki;} private Xowe_wiki wiki;
public Xoctg_view_ctg Ctg() {return ctg;} private Xoctg_view_ctg ctg;
public Xoctg_catpage_ctg Ctg() {return ctg;} private Xoctg_catpage_ctg ctg;
public void Test_bld_rslts_lnk(boolean next, String ctg_str, String expd) {
byte[] actl = ctg_html.Fmtr(Xoa_ctg_mgr.Tid_page).Grp_max_(0).Bld_bwd_fwd(wiki, Xoa_ttl.Parse(wiki, Bry_.new_a7(ctg_str)), ctg.Grp_by_tid(Xoa_ctg_mgr.Tid_page));
Xoctg_fmt_grp.Grp__max = 0;
byte[] actl = ctg_html.Fmt(Xoa_ctg_mgr.Tid_page).Bld_bwd_fwd(wiki, Xoa_ttl.Parse(wiki, Bry_.new_a7(ctg_str)), ctg.Grp_by_tid(Xoa_ctg_mgr.Tid_page));
Tfds.Eq_str_lines(expd, String_.new_u8(actl));
Xoctg_fmt_grp.Grp__max = 200;
}
public Xoh_ctg_page_fxt Init_ctg_name_(String v) {ctg.Name_(Bry_.new_u8(v)); return this;}
public Xoh_ctg_page_fxt Init_ctg_pages_(int bgn, int count) {ctg.Pages().Bgn_(bgn).All_(count).End_(count); return this;}
public Xoh_ctg_page_fxt Init_ctg_files_(int bgn, int count) {ctg.Files().Bgn_(bgn).All_(count).End_(count); return this;}
public Xoh_ctg_page_fxt Init_itm_page(String... titles) {ctg.Pages().Itms_(itms_(Xoa_ctg_mgr.Tid_page, titles)).End_(titles.length); return this;}
public Xoh_ctg_page_fxt Init_itm_file(String... titles) {ctg.Files().Itms_(itms_(Xoa_ctg_mgr.Tid_file, titles)).End_(titles.length); return this;}
public Xoh_ctg_page_fxt Init_itm_ctg(String... titles) {ctg.Subcs().Itms_(itms_(Xoa_ctg_mgr.Tid_subc, titles)).End_(titles.length); return this;}
Xoctg_view_itm[] itms_(byte tid, String... titles) {
int len = titles.length;
Xoctg_view_itm[] rv = new Xoctg_view_itm[len];
for (int i = 0; i < len; i++) {
String title = titles[i];
byte[] title_bry = Bry_.new_u8(title);
Xoa_ttl ttl = Xoa_ttl.Parse(wiki, title_bry);
rv[i] = new Xoctg_view_itm().Set__page(tid, 0).Set__ttl__sortkey(ttl, ttl.Page_txt());
public Xoh_ctg_page_fxt Init_grp__pages(int bgn, int count) {ctg.Pages().Init(bgn, count); return this;}
public Xoh_ctg_page_fxt Init_grp__files(int bgn, int count) {ctg.Files().Init(bgn, count); return this;}
public Xoh_ctg_page_fxt Init_itms__pages(String... titles) {return Init_itms(Xoa_ctg_mgr.Tid_page, titles);}
public Xoh_ctg_page_fxt Init_itms__files(String... titles) {return Init_itms(Xoa_ctg_mgr.Tid_file, titles);}
public Xoh_ctg_page_fxt Init_itms__subcs(String... titles) {return Init_itms(Xoa_ctg_mgr.Tid_subc, titles);}
private Xoh_ctg_page_fxt Init_itms(byte tid, String[] ttls) {
int len = ttls.length;
Xoctg_catpage_grp grp = ctg.Grp_by_tid(tid);
for (int i = 0; i < len; ++i) {
Xoa_ttl ttl = Xoa_ttl.Parse(wiki, Bry_.new_u8(ttls[i]));
grp.Itms__add(new Xoctg_catpage_itm(i, ttl, ttl.Page_txt()));
}
return rv;
grp.Itms__make();
return this;
}
public void Test_html_page(byte tid, byte grp_char_0, String expd) {
Xoctg_fmtr_all list_mgr = ctg_html.Fmtr(tid);
Xoctg_fmtr_itm fmtr_itm = list_mgr.Fmtr_itm();
Xoctg_view_grp list = ctg.Grp_by_tid(tid);
fmtr_itm.Init_from_all(wiki, wiki.Lang(), Xoh_wtr_ctx.Basic, ctg, list_mgr, list, list.Len());
fmtr_itm.Init_from_grp(new byte[] {grp_char_0}, 0);
fmtr_itm.Col_idx_(0, 0);
Xoctg_fmt_grp list_mgr = ctg_html.Fmt(tid);
Xoctg_fmt_itm_base itm_fmt = list_mgr.Itm_fmt();
Xoctg_catpage_grp list = ctg.Grp_by_tid(tid);
itm_fmt.Init_from_ltr(wiki, list);
itm_fmt.Set_ltr_and_bgn(new byte[] {grp_char_0}, 0);
itm_fmt.Col_end_(0, 0);
Bry_bfr bfr = wiki.Utl__bfr_mkr().Get_b512();
fmtr_itm.Bfr_arg__add(bfr);
itm_fmt.Bfr_arg__add(bfr);
Tfds.Eq_str_lines(expd, bfr.To_str_and_rls());
}
public void Test_html_grp(byte tid, String expd) {
Xoctg_fmtr_all list_mgr = ctg_html.Fmtr(tid);
Xoctg_fmtr_grp fmtr_grp = ctg_html.Fmtr_grp();
fmtr_grp.Init_from_all(wiki, wiki.Lang(), Xoh_wtr_ctx.Basic, ctg, list_mgr, ctg.Grp_by_tid(tid));
Xoctg_fmt_grp list_mgr = ctg_html.Fmt(tid);
Xoctg_fmt_ltr fmtr_grp = new Xoctg_fmt_ltr(list_mgr.Itm_fmt());
fmtr_grp.Init_from_grp(wiki, ctg.Grp_by_tid(tid));
Bry_bfr bfr = wiki.Utl__bfr_mkr().Get_b512();
fmtr_grp.Bfr_arg__add(bfr);
Tfds.Eq_str_lines(expd, bfr.To_str_and_rls());
}
public void Test_html_all(byte tid, String expd) {
Bry_bfr bfr = wiki.Utl__bfr_mkr().Get_b512();
ctg_html.Bld_all(bfr, wiki, wiki.Lang(), Xoh_wtr_ctx.Basic, ctg, tid);
ctg_html.Fmt(tid).Write_catpage_grp(bfr, wiki, wiki.Lang(), ctg);
Tfds.Eq_str_lines(expd, bfr.To_str_and_rls());
}
}

@ -15,9 +15,10 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.wikis.ctgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.wikis.*;
package gplx.xowa.addons.wikis.ctgs.htmls.catpages; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*;
import gplx.core.primitives.*; import gplx.core.net.*; import gplx.core.net.qargs.*;
public class Xoctg_url {
import gplx.xowa.addons.wikis.ctgs.htmls.catpages.fmts.*;
public class Xoctg_catpage_url {
public byte[][] Grp_idxs() {return grp_idxs;} private byte[][] grp_idxs = new byte[3][];
public byte[] Grp_fwds() {return grp_fwds;} private byte[] grp_fwds = new byte[3];
private void Clear() {
@ -26,7 +27,7 @@ public class Xoctg_url {
grp_idxs[i] = null;
}
}
public Xoctg_url Parse(Gfo_usr_dlg usr_dlg, Xoa_url url) {
public Xoctg_catpage_url Parse(Gfo_usr_dlg usr_dlg, Xoa_url url) {
this.Clear();
Gfo_qarg_itm[] args = url.Qargs_ary();
int len = args.length;
@ -59,14 +60,24 @@ public class Xoctg_url {
}
}
public static final byte Tid_all_bgn = 0, Tid_subc_bgn = 1, Tid_subc_end = 2, Tid_file_bgn = 3, Tid_file_end = 4, Tid_page_bgn = 5, Tid_page_end = 6, Tid_all_end = 8;
public static final byte[]
Url_arg_from = Bry_.new_a7("from")
, Url_arg_until = Bry_.new_a7("until")
, Url_arg_subc_bgn = Bry_.new_a7("subcatfrom")
, Url_arg_subc_end = Bry_.new_a7("subcatuntil")
, Url_arg_page_bgn = Bry_.new_a7("pagefrom")
, Url_arg_page_end = Bry_.new_a7("pageuntil")
, Url_arg_file_bgn = Bry_.new_a7("filefrom")
, Url_arg_file_end = Bry_.new_a7("fileuntil")
;
public static final Hash_adp_bry Arg_keys = Hash_adp_bry.ci_a7()
.Add_bry_byte(Xoctg_fmtr_all.Url_arg_from, Tid_all_bgn)
.Add_bry_byte(Xoctg_fmtr_all.Url_arg_until, Tid_all_end)
.Add_bry_byte(Xoctg_fmtr_all.Url_arg_subc_bgn, Tid_subc_bgn)
.Add_bry_byte(Xoctg_fmtr_all.Url_arg_subc_end, Tid_subc_end)
.Add_bry_byte(Xoctg_fmtr_all.Url_arg_file_bgn, Tid_file_bgn)
.Add_bry_byte(Xoctg_fmtr_all.Url_arg_file_end, Tid_file_end)
.Add_bry_byte(Xoctg_fmtr_all.Url_arg_page_bgn, Tid_page_bgn)
.Add_bry_byte(Xoctg_fmtr_all.Url_arg_page_end, Tid_page_end)
.Add_bry_byte(Url_arg_from , Tid_all_bgn)
.Add_bry_byte(Url_arg_until , Tid_all_end)
.Add_bry_byte(Url_arg_subc_bgn , Tid_subc_bgn)
.Add_bry_byte(Url_arg_subc_end , Tid_subc_end)
.Add_bry_byte(Url_arg_file_bgn , Tid_file_bgn)
.Add_bry_byte(Url_arg_file_end , Tid_file_end)
.Add_bry_byte(Url_arg_page_bgn , Tid_page_bgn)
.Add_bry_byte(Url_arg_page_end , Tid_page_end)
;
}

@ -15,10 +15,10 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.wikis.ctgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.wikis.*;
package gplx.xowa.addons.wikis.ctgs.htmls.catpages; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*;
import org.junit.*; import gplx.xowa.apps.urls.*;
public class Xoctg_url_tst {
@Before public void init() {fxt.Clear();} private Xoctg_url_fxt fxt = new Xoctg_url_fxt();
public class Xoctg_catpage_url_tst {
@Before public void init() {fxt.Clear();} private Xoctg_catpage_url_fxt fxt = new Xoctg_catpage_url_fxt();
@Test public void Basic() {
fxt.Test_parse("A?subcatfrom=B&filefrom=C&pagefrom=D", fxt.url().Grp_idxs_("B", "C", "D").Grp_fwds_(Bool_.Y_byte, Bool_.Y_byte, Bool_.Y_byte));
fxt.Test_parse("A?subcatuntil=B&fileuntil=C&pageuntil=D", fxt.url().Grp_idxs_("B", "C", "D").Grp_fwds_(Bool_.N_byte, Bool_.N_byte, Bool_.N_byte));
@ -26,42 +26,42 @@ public class Xoctg_url_tst {
fxt.Test_parse("A?until=B", fxt.url().Grp_idxs_("B", "B", "B").Grp_fwds_(Bool_.N_byte, Bool_.N_byte, Bool_.N_byte));
}
}
class Xoctg_url_fxt {
public Xoctg_url_chkr url() {return expd.Clear();} private Xoctg_url_chkr expd;
class Xoctg_catpage_url_fxt {
public Xoctg_catpage_url_chkr url() {return expd.Clear();} private Xoctg_catpage_url_chkr expd;
public void Clear() {
if (parser == null) {
Xoa_app app = Xoa_app_fxt.Make__app__edit();
parser = app.User().Wikii().Utl__url_parser();
page_url = Xoa_url.blank();
ctg_url = new Xoctg_url();
expd = new Xoctg_url_chkr();
ctg_url = new Xoctg_catpage_url();
expd = new Xoctg_catpage_url_chkr();
}
} private Xow_url_parser parser; Xoa_url page_url; Xoctg_url ctg_url;
public void Test_parse(String url_str, Xoctg_url_chkr expd) {
} private Xow_url_parser parser; Xoa_url page_url; Xoctg_catpage_url ctg_url;
public void Test_parse(String url_str, Xoctg_catpage_url_chkr expd) {
page_url = parser.Parse(Bry_.new_u8(url_str));
ctg_url.Parse(Gfo_usr_dlg_.Test(), page_url);
expd.Chk(ctg_url);
expd.Clear();
}
}
class Xoctg_url_chkr {
public Xoctg_url_chkr Grp_idxs_(String subc, String file, String page) {
class Xoctg_catpage_url_chkr {
public Xoctg_catpage_url_chkr Grp_idxs_(String subc, String file, String page) {
grp_idxs[Xoa_ctg_mgr.Tid_subc] = Bry_.new_a7(subc);
grp_idxs[Xoa_ctg_mgr.Tid_file] = Bry_.new_a7(file);
grp_idxs[Xoa_ctg_mgr.Tid_page] = Bry_.new_a7(page);
return this;
} byte[][] grp_idxs = new byte[Xoa_ctg_mgr.Tid__max][];
public Xoctg_url_chkr Grp_fwds_(byte subc, byte file, byte page) {
public Xoctg_catpage_url_chkr Grp_fwds_(byte subc, byte file, byte page) {
grp_fwds[Xoa_ctg_mgr.Tid_subc] = subc;
grp_fwds[Xoa_ctg_mgr.Tid_file] = file;
grp_fwds[Xoa_ctg_mgr.Tid_page] = page;
return this;
} byte[] grp_fwds = new byte[Xoa_ctg_mgr.Tid__max];
public void Chk(Xoctg_url actl) {
public void Chk(Xoctg_catpage_url actl) {
Tfds.Eq_ary_str(String_.Ary(grp_idxs), String_.Ary(actl.Grp_idxs()));
Tfds.Eq_ary(grp_fwds, actl.Grp_fwds());
}
public Xoctg_url_chkr Clear() {
public Xoctg_catpage_url_chkr Clear() {
int len = Xoa_ctg_mgr.Tid__max;
for (int i = 0; i < len; i++) {
grp_idxs[i] = null;

@ -0,0 +1,40 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.htmls.catpages.doms; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.*;
public class Xoctg_catpage_ctg {
public Xoctg_catpage_ctg(byte[] name) {this.name = name;}
public byte[] Name() {return name;} private final byte[] name;
public Xoctg_catpage_grp Subcs() {return subcs;} private final Xoctg_catpage_grp subcs = new Xoctg_catpage_grp(Xoa_ctg_mgr.Tid_subc);
public Xoctg_catpage_grp Pages() {return pages;} private final Xoctg_catpage_grp pages = new Xoctg_catpage_grp(Xoa_ctg_mgr.Tid_page);
public Xoctg_catpage_grp Files() {return files;} private final Xoctg_catpage_grp files = new Xoctg_catpage_grp(Xoa_ctg_mgr.Tid_file);
public int Total() {return subcs.Total() + pages.Total() + files.Total();}
public Xoctg_catpage_grp Grp_by_tid(byte tid) {
switch (tid) {
case Xoa_ctg_mgr.Tid_subc: return subcs;
case Xoa_ctg_mgr.Tid_page: return pages;
case Xoa_ctg_mgr.Tid_file: return files;
default: throw Err_.new_unhandled(tid);
}
}
public void Make_itms() {
for (byte i = 0; i < Xoa_ctg_mgr.Tid__max; ++i) {
Xoctg_catpage_grp grp = Grp_by_tid(i);
grp.Itms__make();
}
}
}

@ -0,0 +1,44 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.htmls.catpages.doms; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.*;
public class Xoctg_catpage_grp {
public Xoctg_catpage_grp(byte tid) {this.tid = tid;}
public byte Tid() {return tid;} private byte tid; // subc|page|file
public int Bgn() {return bgn;} private int bgn;
public int End() {return end;} private int end;
public int Len() {return end - bgn;}
public int Total() {return total;} private int total;
public Xoctg_catpage_itm[] Itms() {return itms;} private Xoctg_catpage_itm[] itms = Xoctg_catpage_itm.Ary_empty;
public byte[] Itms__nth_sortkey() {return itms__nth_sortkey;}
public Xoctg_catpage_itm Itms__get_at_0th() {return Itms__get_at(0);}
public Xoctg_catpage_itm Itms__get_at_nth() {return Itms__get_at(itms.length - 1);}
private Xoctg_catpage_itm Itms__get_at(int i) {
if (i < 0 || i >= itms.length) throw Err_.new_wo_type("ctg.view: i is out of bounds", "i", i, "len", itms.length, "tid", tid);
Xoctg_catpage_itm rv = itms[i]; if (rv == null) throw Err_.new_wo_type("ctg.view: itm is null", "i", i, "len", itms.length, "tid", tid);
return rv;
}
public void Itms__add(Xoctg_catpage_itm sub) {tmp_list.Add(sub);}
public void Itms__make() {
itms = (Xoctg_catpage_itm[])tmp_list.To_ary(Xoctg_catpage_itm.class);
total = end = itms.length;
}
public Xoctg_catpage_grp Itms__nth_sortkey_(byte[] v) {itms__nth_sortkey = v; return this;} private byte[] itms__nth_sortkey;
public void Init(int bgn, int end) {this.bgn = bgn; this.end = end;} // TEST:
public List_adp Itms_list() {return tmp_list;} private final List_adp tmp_list = List_adp_.New(); // TEST
}

@ -0,0 +1,33 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.htmls.catpages.doms; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.*;
public class Xoctg_catpage_itm implements gplx.CompareAble {
public Xoctg_catpage_itm(int page_id, Xoa_ttl page_ttl, byte[] sort_key) {
this.page_id = page_id;
this.page_ttl = page_ttl;
this.sort_key = sort_key.length == 0 ? page_ttl.Page_db() : sort_key; // v1 will not have sortkey data; PAGE:s.w:Category:Computer_science DATE:2015-11-22
}
public int Page_id() {return page_id;} private int page_id;
public Xoa_ttl Page_ttl() {return page_ttl;} private Xoa_ttl page_ttl;
public byte[] Sort_key() {return sort_key;} private byte[] sort_key;
public boolean Missing() {return missing;} private boolean missing; // not used; remove?;
public void Missing_y_() {missing = true;}
public int compareTo(Object obj) {Xoctg_catpage_itm comp = (Xoctg_catpage_itm)obj; return Int_.Compare(page_id, comp.Page_id());}
public static final Xoctg_catpage_itm[] Ary_empty = new Xoctg_catpage_itm[0];
}

@ -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.addons.wikis.ctgs.htmls.catpages.fmts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.*;
import gplx.xowa.addons.wikis.ctgs.htmls.catpages.doms.*;
class Xoctg_catpage_itm_sorter implements gplx.core.lists.ComparerAble {
public int compare(Object lhsObj, Object rhsObj) {
Xoctg_catpage_itm lhs = (Xoctg_catpage_itm)lhsObj;
Xoctg_catpage_itm rhs = (Xoctg_catpage_itm)rhsObj;
return Bry_.Compare(lhs.Sort_key(), rhs.Sort_key());
}
public static final Xoctg_catpage_itm_sorter Sorter = new Xoctg_catpage_itm_sorter();
}

@ -0,0 +1,110 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.htmls.catpages.fmts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.*;
import gplx.xowa.langs.*; import gplx.xowa.langs.msgs.*; import gplx.xowa.htmls.core.htmls.*; import gplx.langs.htmls.encoders.*;
import gplx.xowa.wikis.nss.*;
import gplx.xowa.addons.wikis.ctgs.htmls.catpages.doms.*;
public class Xoctg_fmt_grp { // subc|page|file
private final byte tid;
private final byte[] div_id, url_arg_bgn, url_arg_end;
private final int msg_label_id, msg_stats_id;
private final Xoctg_fmt_ltr itms_fmt;
Xoctg_fmt_grp(byte tid, Xoctg_fmt_itm_base itm_fmt, int msg_label_id, int msg_stats_id, byte[] url_arg_bgn, byte[] url_arg_end, byte[] div_id) {
this.tid = tid;
this.itm_fmt = itm_fmt;
this.itms_fmt = new Xoctg_fmt_ltr(itm_fmt);
this.msg_label_id = msg_label_id; this.msg_stats_id = msg_stats_id;
this.url_arg_bgn = url_arg_bgn; this.url_arg_end = url_arg_end; this.div_id = div_id;
}
public Xoctg_fmt_itm_base Itm_fmt() {return itm_fmt;} private final Xoctg_fmt_itm_base itm_fmt;
public void Write_catpage_grp(Bry_bfr bfr, Xow_wiki wiki, Xol_lang_itm lang, Xoctg_catpage_ctg dom_ctg) { // TEST:
Xoctg_catpage_grp dom_grp = dom_ctg.Grp_by_tid(tid);
if (dom_grp.Itms().length == 0) return; // no items in grp; EX: 0 items in File
// get msgs
Xow_msg_mgr msg_mgr = wiki.Msg_mgr();
byte[] msg_label_bry = msg_mgr.Val_by_id_args(msg_label_id, dom_ctg.Name());
byte[] msg_stats_bry = msg_mgr.Val_by_id_args(msg_stats_id, dom_grp.Len(), dom_grp.Total());
// get nav html; next / previous 200
Xoa_ttl ctg_ttl = wiki.Ttl_parse(Xow_ns_.Tid__category, dom_ctg.Name());
byte[] nav_html = this.Bld_bwd_fwd(wiki, ctg_ttl, dom_grp);
// sort; init grp; write
Array_.Sort(dom_grp.Itms(), Xoctg_catpage_itm_sorter.Sorter); // NOTE: must assert sorted for v1; PAGE:s.w:Category:Computer_science; DATE:2015-11-22
itms_fmt.Init_from_grp(wiki, dom_grp);
Fmt__ctg.Bld_many(bfr, div_id, msg_label_bry, msg_stats_bry, nav_html, lang.Key_bry(), lang.Dir_ltr_bry(), itms_fmt);
}
public byte[] Bld_bwd_fwd(Xow_wiki wiki, Xoa_ttl ttl, Xoctg_catpage_grp view_grp) { // TEST:
if (view_grp.Total() < Grp__max) return Bry_.Empty;
Bry_bfr bfr = wiki.Utl__bfr_mkr().Get_k004();
Html_nav_bry(bfr, wiki, ttl, view_grp, Bool_.N);
Html_nav_bry(bfr, wiki, ttl, view_grp, Bool_.Y);
return bfr.To_bry_and_rls();
}
private void Html_nav_bry(Bry_bfr bfr, Xow_wiki wiki, Xoa_ttl ttl, Xoctg_catpage_grp view_grp, boolean type_is_bgn) {
Bry_bfr href_bfr = wiki.Utl__bfr_mkr().Get_b512();
// get nav_href; EX:href="/wiki/Category:Ctg_1?pageuntil=A1#mw-pages"
wiki.Html__href_wtr().Build_to_bfr(href_bfr, wiki.App(), Xoh_wtr_ctx.Basic, wiki.Domain_bry(), ttl);
byte[] arg_idx_lbl = null; byte[] arg_sortkey = null;
if (type_is_bgn) {
arg_idx_lbl = url_arg_bgn;
arg_sortkey = view_grp.Itms__nth_sortkey();
if (arg_sortkey == null) arg_sortkey = view_grp.Itms__get_at_nth().Sort_key();
}
else {
arg_idx_lbl = url_arg_end;
arg_sortkey = view_grp.Itms__get_at_0th().Sort_key();
}
href_bfr.Add_byte(Byte_ascii.Question).Add(arg_idx_lbl).Add_byte(Byte_ascii.Eq); // filefrom=
Gfo_url_encoder_.Http_url.Encode(href_bfr, arg_sortkey); // Abc
href_bfr.Add_byte(Byte_ascii.Hash).Add(div_id); // #mw-subcategories
byte[] nav_href = href_bfr.To_bry_and_rls();
// get nav_text
int nav_text_id = type_is_bgn ? Xol_msg_itm_.Id_next_results : Xol_msg_itm_.Id_prev_results;
byte[] nav_text = wiki.Msg_mgr().Val_by_id_args(nav_text_id, Grp__max); // next 200 / previous 200
// fmt
Fmt__nav.Bld_many(bfr, nav_href, ttl.Full_url(), nav_text);
}
public static int Grp__max = 200;
private static final Bry_fmt
Fmt__nav = Bry_fmt.Auto_nl_skip_last
( ""
, " (<a href=\"~{nav_href}\" class=\"xowa_nav\" title=\"~{nav_title}\">~{nav_text}</a>)"
)
, Fmt__ctg = Bry_fmt.Auto_nl_skip_last
( ""
, "<div id=\"~{div_id}\">"
, " <h2>~{msg_label_bry}</h2>"
, " <p>~{msg_stats_bry}</p>~{nav_html}"
, " <div lang=\"~{lang_key}\" dir=\"~{lang_ltr}\" class=\"mw-content-~{lang_ltr}\">"
, " <table style=\"width: 100%;\">"
, " <tr style=\"vertical-align: top;\">~{grps}"
, " </tr>"
, " </table>"
, " </div>~{nav_html}"
, "</div>"
);
public static Xoctg_fmt_grp New__subc() {return new Xoctg_fmt_grp(Xoa_ctg_mgr.Tid_subc, new Xoctg_fmt_itm_subc(), Xol_msg_itm_.Id_ctg_subc_header, Xol_msg_itm_.Id_ctg_subc_count, Xoctg_catpage_url.Url_arg_subc_bgn, Xoctg_catpage_url.Url_arg_subc_end, Bry_.new_a7("mw-subcategories"));}
public static Xoctg_fmt_grp New__page() {return new Xoctg_fmt_grp(Xoa_ctg_mgr.Tid_page, new Xoctg_fmt_itm_page(), Xol_msg_itm_.Id_ctg_page_header, Xol_msg_itm_.Id_ctg_page_count, Xoctg_catpage_url.Url_arg_page_bgn, Xoctg_catpage_url.Url_arg_page_end, Bry_.new_a7("mw-pages"));}
public static Xoctg_fmt_grp New__file() {return new Xoctg_fmt_grp(Xoa_ctg_mgr.Tid_file, new Xoctg_fmt_itm_file(), Xol_msg_itm_.Id_ctg_file_header, Xol_msg_itm_.Id_ctg_file_count, Xoctg_catpage_url.Url_arg_file_bgn, Xoctg_catpage_url.Url_arg_file_end, Bry_.new_a7("mw-category-media"));}
}

@ -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.addons.wikis.ctgs.htmls.catpages.fmts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.*;
import gplx.langs.htmls.*; import gplx.xowa.htmls.*; import gplx.xowa.htmls.hrefs.*; import gplx.xowa.htmls.core.wkrs.lnkis.htmls.*; import gplx.xowa.htmls.core.htmls.*;
import gplx.xowa.langs.*; import gplx.xowa.langs.msgs.*;
import gplx.xowa.users.history.*;
import gplx.xowa.addons.wikis.ctgs.htmls.catpages.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.doms.*;
public abstract class Xoctg_fmt_itm_base implements gplx.core.brys.Bfr_arg {
private final Bry_bfr tmp_bfr = Bry_bfr_.New();
private Xow_wiki wiki;
private Xoctg_catpage_grp grp;
private byte[] ltr_cur; private int loop_bgn; private int col_end;
public int Loop_end_idx() {return loop_end_idx;} private int loop_end_idx;
public boolean Loop_ends_at_col() {return loop_ends_at_col;} private boolean loop_ends_at_col;
public void Col_end_(int col_bgn, int col_idx) {
this.col_end = col_bgn + Calc_col_len(grp.Len(), col_idx, Cols_max);
}
public void Init_from_ltr(Xow_wiki wiki, Xoctg_catpage_grp grp) {this.wiki = wiki; this.grp = grp;}
public void Set_ltr_and_bgn(byte[] ltr_cur, int loop_bgn) {this.ltr_cur = ltr_cur; this.loop_bgn = loop_bgn;}
public void Bfr_arg__add(Bry_bfr bfr) {
// init vars
Xoh_href_parser href_parser = wiki.App().Html__href_parser();
Xou_history_mgr history_mgr = wiki.App().User().History_mgr();
int len = grp.Len();
// loop over itms;
for (int i = loop_bgn; i < len; i++) {
// reached end of col; exit
if (i == col_end) {
loop_end_idx = i;
loop_ends_at_col = true;
return;
}
// get sortkey
Xoctg_catpage_itm itm = grp.Itms()[i];
byte[] itm_sortkey = itm.Sort_key();
// reached end of ltr; exit
if (!Bry_.Has_at_bgn(itm_sortkey, ltr_cur, 0, itm_sortkey.length)) {
loop_end_idx = i;
loop_ends_at_col = i == col_end;
return;
}
Bld_html(bfr, wiki, history_mgr, href_parser, itm, itm.Page_ttl());
}
loop_end_idx = len;
loop_ends_at_col = true;
}
@gplx.Virtual public void Bld_html(Bry_bfr bfr, Xow_wiki wiki, Xou_history_mgr history_mgr, Xoh_href_parser href_parser, Xoctg_catpage_itm itm, Xoa_ttl ttl) {
byte[] itm_full_ttl = Gfh_utl.Escape_html_as_bry(tmp_bfr, ttl.Full_txt_w_ttl_case());// NOTE: ttl.Full_txt() to get full ns; EX: Template:A instead of just "A"
if (itm.Missing())
fmt_missing.Bld_many(bfr, itm.Page_id(), itm_full_ttl);
else {
byte[] itm_href = wiki.Html__href_wtr().Build_to_bry(wiki, ttl);
byte[] itm_atr_cls = Xoh_lnki_wtr.Lnki_cls_visited(history_mgr, wiki.Domain_bry(), ttl.Page_txt()); // NOTE: must be ttl.Page_txt() in order to match Xou_history_mgr.Add
fmt_exists.Bld_many(bfr, itm_href, itm_atr_cls, itm_full_ttl, itm_full_ttl);
}
}
private static final Bry_fmt
fmt_missing = Bry_fmt.Auto_nl_skip_last
( ""
, " <li class=\"xowa-missing-category-entry\"><span title=\"id not found: #~{itm_id} might be talk/user page\">~{itm_text} (missing)</li>"
)
, fmt_exists = Bry_fmt.Auto_nl_skip_last
( ""
, " <li><a href=\"~{itm_href}\"~{itm_atr_cls} title=\"~{itm_title}\">~{itm_text}</a></li>"
)
;
public static final int Cols_max = 3;
public static int Calc_col_len(int grp_len, int col_idx, int max_cols) { // TEST
if (grp_len == 0) return 0; // 0 items in group; return 0;
int max_itms_in_col = ((grp_len - 1) / max_cols) + 1; // EX: grp with 4, 5, 6 items should have max of 2 items in 1 col, so (a) subtract 1; (b) divide by 3; (c) add 1
return col_idx <= ((grp_len - 1) % max_cols) // complicated formula but works; rely on example and note that only 2 or 1 can be returned; EX: 4=2,1,1; 5=2,2,1; 6=2,2,2
? max_itms_in_col
: max_itms_in_col - 1;
}
}

@ -15,14 +15,13 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.wikis.ctgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.wikis.*;
class Xoctg_fmtr_itm_page extends Xoctg_fmtr_itm_base {
}
class Xoctg_fmtr_itm_file extends Xoctg_fmtr_itm_base {
package gplx.xowa.addons.wikis.ctgs.htmls.catpages.fmts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.*;
class Xoctg_fmt_itm_page extends Xoctg_fmt_itm_base {}
class Xoctg_fmt_itm_file extends Xoctg_fmt_itm_base {
// public void Bfr_arg__add(Bry_bfr bfr) {
// html_itm = wiki.Html_mgr().Gallery_xtn_mgr().Html_gallery_itm_img();
// for (int i = list.Bgn(); i < len; i++) {
// Xoctg_view_itm itm = list.Itms()[i];
// Xoctg_catpage_itm itm = list.Itms()[i];
// Xoa_ttl ttl = itm.Ttl();
// byte[] ttl_page = ttl.Page_txt();
// byte[] itm_href = href_parser.Build_to_bry(ttl, wiki);

@ -0,0 +1,69 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.htmls.catpages.fmts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.*;
import gplx.xowa.htmls.core.htmls.*; import gplx.xowa.htmls.hrefs.*;
import gplx.xowa.langs.msgs.*;
import gplx.xowa.addons.wikis.ctgs.htmls.catpages.doms.*;
import gplx.xowa.users.history.*;
class Xoctg_fmt_itm_subc extends Xoctg_fmt_itm_base {
private final Bry_bfr tmp_bfr = Bry_bfr_.New();
@Override public void Bld_html(Bry_bfr bfr, Xow_wiki wiki, Xou_history_mgr history_mgr, Xoh_href_parser href_parser, Xoctg_catpage_itm itm, Xoa_ttl ttl) {
byte[] itm_href = wiki.Html__href_wtr().Build_to_bry(wiki, ttl);
int count_subcs = 0;
int count_pages = 0;
int count_files = 0;
Xow_msg_mgr msg_mgr = wiki.Msg_mgr();
byte[] contains_title = wiki.Msg_mgr().Val_by_id_args(Xol_msg_itm_.Id_ctgtree_subc_counts, count_subcs, count_pages, count_files);
byte[] contains_text = Bld_contains_text(msg_mgr, count_subcs, count_pages, count_files);
byte[] ttl_page = ttl.Page_txt();
fmt_exists.Bld_many(bfr, ttl.Page_db(), ttl_page, itm_href, ttl_page, contains_title, contains_text);
}
private byte[] Bld_contains_text(Xow_msg_mgr msg_mgr, int count_subcs, int count_pages, int count_files) {
if (count_subcs == 0 && count_pages == 0 && count_files == 0) return Bry_.Empty;
tmp_bfr.Add_byte(Byte_ascii.Paren_bgn);
Bld_contains_text_itm(tmp_bfr, msg_mgr, Xol_msg_itm_.Id_ctgtree_subc_counts_ctg, count_subcs);
Bld_contains_text_itm(tmp_bfr, msg_mgr, Xol_msg_itm_.Id_ctgtree_subc_counts_page, count_pages);
Bld_contains_text_itm(tmp_bfr, msg_mgr, Xol_msg_itm_.Id_ctgtree_subc_counts_file, count_files);
tmp_bfr.Add_byte(Byte_ascii.Paren_end);
return tmp_bfr.To_bry_and_clear();
}
private void Bld_contains_text_itm(Bry_bfr bfr, Xow_msg_mgr msg_mgr, int msg_id, int val) {
if (val == 0) return;
if (bfr.Len() > 1) bfr.Add(Bld_contains_text_itm_dlm); // NOTE: 1 b/c Paren_bgn is always added
bfr.Add(msg_mgr.Val_by_id_args(msg_id, val));
} private static final byte[] Bld_contains_text_itm_dlm = Bry_.new_a7(", ");
private static final Bry_fmt
fmt_exists = Bry_fmt.Auto_nl_skip_last
( ""
, " <li>"
, " <div class=\"CategoryTreeSection\">"
, " <div class=\"CategoryTreeItem\">"
, " <span class=\"CategoryTreeBullet\">"
, " <span class=\"CategoryTreeToggle\" style=\"display: none;\" data-ct-title=\"~{itm_data_title}\" title=\"~{itm_title}\" data-ct-state=\"collapsed\">"
, " </span> "
, " </span>"
, " <a href=\"~{itm_href}\" class=\"" + Xoa_ctg_mgr.Html__cls__str + "\">~{itm_text}"
, " </a>"
, " <span title=\"~{itm_contains_title}\" dir=\"ltr\">~{itm_contains_text}"
, " </span>"
, " </div>"
, " <div class=\"CategoryTreeChildren\" style=\"display:none\"></div>"
, " </div>"
, " </li>"
);
}

@ -0,0 +1,82 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.htmls.catpages.fmts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.*;
import gplx.xowa.htmls.core.htmls.*;
import gplx.xowa.langs.*; import gplx.xowa.langs.msgs.*;
import gplx.xowa.addons.wikis.ctgs.htmls.catpages.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.doms.*;
public class Xoctg_fmt_ltr implements gplx.core.brys.Bfr_arg { // "A", "B", "C cont."
private final Xoctg_fmt_itm_base itm_fmt;
private Xoctg_catpage_grp grp;
private byte[] msg__list_continues;
public Xoctg_fmt_ltr(Xoctg_fmt_itm_base itm_fmt) {
this.itm_fmt = itm_fmt;
}
public void Init_from_grp(Xow_wiki wiki, Xoctg_catpage_grp grp) {
this.grp = grp;
this.msg__list_continues = wiki.Msg_mgr().Val_by_id(Xol_msg_itm_.Id_list_continues);
itm_fmt.Init_from_ltr(wiki, grp);
}
public void Bfr_arg__add(Bry_bfr bfr) {
int itms_len = grp.Len(); if (itms_len == 0) return; // no items; exit
int itm_idx = grp.Bgn(); // itm idx; EX: idx=201 in len=500
int col_idx = 0; // col idx; EX: 3 cols; idx = 0, 1, 2
boolean start_new_col = true;
byte[] ltr_prv = Bry_.Empty;
// loop itms until no more itms
while (itm_idx < itms_len) {
Xoctg_catpage_itm itm = grp.Itms()[itm_idx];
// get ltr_head; EX: "C" or "C cont."
byte[] itm_sortkey = itm.Sort_key();
byte[] ltr_cur = gplx.core.intls.Utf8_.Get_char_at_pos_as_bry(itm_sortkey, 0);
byte[] ltr_head = Bry_.Eq(ltr_prv, ltr_cur)
? Bry_.Add(ltr_prv, Byte_ascii.Space_bry, msg__list_continues) // new col uses same ltr as last itm in old col; add "cont."; EX: "C cont."
: ltr_cur; // else, just use ltr; EX: "C"
ltr_prv = ltr_cur;
// start new column if needed
if (start_new_col) {
itm_fmt.Col_end_(itm_idx, col_idx++); // set col_end; note col starts at itm_idx
Fmt__col_bgn.Bld_many(bfr, 100 / Xoctg_fmt_itm_base.Cols_max); // width:33%
}
// set ltr and idx
itm_fmt.Set_ltr_and_bgn(ltr_prv, itm_idx);
// loop until (a) end of ltr or (b) end of col
Fmt__tbl.Bld_many(bfr, ltr_head, itm_fmt);
itm_idx = itm_fmt.Loop_end_idx();
start_new_col = itm_fmt.Loop_ends_at_col();
// end column if needed
if (start_new_col)
Fmt__col_end.Bld_many(bfr);
}
}
private static final Bry_fmt
Fmt__tbl = Bry_fmt.Auto_nl_skip_last
( ""
, " <h3>~{ltr_head}</h3>" // EX: "A", "A cont."
, " <ul>~{itms}"
, " </ul>"
)
, Fmt__col_bgn = Bry_fmt.New("\n <td style=\"width: ~{width}%;\">")
, Fmt__col_end = Bry_fmt.New("\n </td>");
}

@ -0,0 +1,56 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.htmls.pageboxs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*;
import gplx.core.lists.hashs.*;
class Xoctg_pagebox_hash {
private final Ordered_hash hash_by_ttl = Ordered_hash_.New_bry();
private final Hash_adp__int hash_by_id = new Hash_adp__int();
public int Len() {return hash_by_ttl.Len();}
public Xoctg_pagebox_itm Get_at(int i) {return (Xoctg_pagebox_itm)hash_by_ttl.Get_at(i);}
public Xoctg_pagebox_itm Get_by_ttl(byte[] full_db) {return (Xoctg_pagebox_itm)hash_by_ttl.Get_by(full_db);}
public Xoctg_pagebox_itm Get_by_id(int page_id) {return (Xoctg_pagebox_itm)hash_by_id.Get_by(page_id);}
public Xoctg_pagebox_itm[] To_ary_and_clear() {
hash_by_id.Clear();
return (Xoctg_pagebox_itm[])hash_by_ttl.To_ary_and_clear(Xoctg_pagebox_itm.class);
}
public Xoctg_pagebox_itm Add_by_ttl(Xoa_ttl ttl) {
Xoctg_pagebox_itm rv = Xoctg_pagebox_itm.New_by_ttl(ttl);
hash_by_ttl.Add(ttl.Full_db(), rv);
return rv;
}
public void Sort_and_fill_ids() {
// sort
hash_by_ttl.Sort_by(Xoctg_pagebox_hash_sorter.Sorter);
// fill ids_hash
hash_by_id.Clear();
int len = hash_by_ttl.Len();
for (int i = 0; i < len; ++i) {
Xoctg_pagebox_itm itm = (Xoctg_pagebox_itm)hash_by_ttl.Get_at(i);
hash_by_id.Add(itm.Id(), itm);
}
}
}
class Xoctg_pagebox_hash_sorter implements gplx.core.lists.ComparerAble {
public int compare(Object lhsObj, Object rhsObj) {
Xoctg_pagebox_itm lhs = (Xoctg_pagebox_itm)lhsObj;
Xoctg_pagebox_itm rhs = (Xoctg_pagebox_itm)rhsObj;
return -Int_.Compare(lhs.Count__all(), rhs.Count__all());
}
public static final Xoctg_pagebox_hash_sorter Sorter = new Xoctg_pagebox_hash_sorter(); Xoctg_pagebox_hash_sorter() {}
}

@ -0,0 +1,50 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.htmls.pageboxs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*;
import gplx.xowa.wikis.pages.wtxts.*;
public class Xoctg_pagebox_itm {
public Xoctg_pagebox_itm(Xoa_ttl ttl) {
this.ttl = ttl;
}
public Xoa_ttl Ttl() {return ttl;} private final Xoa_ttl ttl;
public int Id() {return id;} private int id;
public DateAdp Timestamp() {return timestamp;} private DateAdp timestamp;
public boolean Hidden() {return hidden;} private boolean hidden;
public int Count__subcs() {return count__subcs;} private int count__subcs;
public int Count__pages() {return count__pages;} private int count__pages;
public int Count__files() {return count__files;} private int count__files;
public int Count__all() {return count__all;} private int count__all;
public void Load_by_db(int id, DateAdp timestamp) {
this.id = id; this.timestamp = timestamp;
}
public void Load_by_cat_core(boolean hidden, int count__subcs, int count__pages, int count__files) {
this.hidden = hidden;
this.count__subcs = count__subcs; this.count__pages = count__pages; this.count__files = count__files;
this.count__all = count__subcs + count__pages + count__files;
}
public static Xoctg_pagebox_itm New_by_ttl(Xoa_ttl ttl) {return new Xoctg_pagebox_itm(ttl);}
public static Xoctg_pagebox_itm[] New_ary(Xoa_page pg) {
int len = pg.Wtxt().Ctgs__len();
Xoctg_pagebox_itm[] rv = new Xoctg_pagebox_itm[len];
for (int i = 0; i < len; ++i)
rv[i] = New_by_ttl(pg.Wtxt().Ctgs__get_at(i));
return rv;
}
}

@ -0,0 +1,73 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.htmls.pageboxs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*;
import gplx.dbs.*; import gplx.xowa.addons.wikis.ctgs.dbs.*; import gplx.xowa.wikis.data.tbls.*;
class Xoctg_pagebox_loader implements Select_in_cbk {
private final Xoctg_pagebox_hash hash; private final byte[] page_url;
public Xoctg_pagebox_loader(Xoctg_pagebox_hash hash, byte[] page_url) {
this.hash = hash; this.page_url = page_url;
}
public int Hash_max() {return hash.Len();}
public void Write_sql(Bry_bfr bfr, int idx) {
Xoctg_pagebox_itm page = (Xoctg_pagebox_itm)hash.Get_at(idx);
bfr.Add_int_variable(page.Id());
}
public void Read_data(Db_rdr rdr) {
int cat_id = rdr.Read_int("cat_id");
Xoctg_pagebox_itm page = (Xoctg_pagebox_itm)hash.Get_by_id(cat_id);
if (page == null) {// unlikely, but possible for itms to exist in cat_links, but not in cat_core; log and return;
Gfo_usr_dlg_.Instance.Warn_many("", "", "cat_id in cat_link but not in cat_core; page=~{0} cat_id=~{0}", page_url, cat_id);
}
page.Load_by_cat_core(rdr.Read_bool_by_byte("cat_hidden"), rdr.Read_int("cat_pages"), rdr.Read_int("cat_subcats"), rdr.Read_int("cat_files"));
}
public void Select_catlinks_by_page(Xow_wiki wiki, Db_conn cat_link_conn, Xoctg_pagebox_hash hash, int page_id) {
// init
Db_attach_mgr attach_mgr = new Db_attach_mgr(cat_link_conn, new Db_attach_itm("page_db", wiki.Data__core_mgr().Db__core().Conn()));
String sql = String_.Concat_lines_nl_skip_last // ANSI.Y
( "SELECT cl.cl_to_id"
, ", cl.cl_timestamp_unix"
, ", p.page_namespace"
, ", p.page_title"
, "FROM cat_link cl"
, " JOIN <page_db>page p ON cl.cl_to_id = p.page_id"
, "WHERE cl.cl_from = " + Int_.To_str(page_id)
);
sql = attach_mgr.Resolve_sql(sql);
// select
attach_mgr.Attach();
Db_rdr rdr = cat_link_conn.Stmt_sql(sql).Exec_select__rls_auto();
try {
while (rdr.Move_next()) {
Xoa_ttl ttl = wiki.Ttl_parse(rdr.Read_int("page_namespace"), rdr.Read_bry_by_str("page_title"));
// check if ttl exists already in hash; add it if not; check is not needed now b/c html_dbs will never put itms in hash, but may need in future if merging "wtxt" and "ctgs_dbs"
Xoctg_pagebox_itm itm = (Xoctg_pagebox_itm)hash.Get_by_ttl(ttl.Full_db());
if (itm == null)
itm = hash.Add_by_ttl(ttl);
itm.Load_by_db(rdr.Read_int("cl_to_id"), DateAdp_.unixtime_utc_ms_(rdr.Read_long("cl_timestamp_unix")));
}
}
finally {
rdr.Rls();
attach_mgr.Detach();
}
// hash items by id
hash.Sort_and_fill_ids();
}
}

@ -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.addons.wikis.ctgs.htmls.pageboxs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*;
import gplx.xowa.htmls.core.htmls.*;
import gplx.xowa.addons.wikis.ctgs.htmls.pageboxs.singles.*; import gplx.xowa.addons.wikis.ctgs.htmls.pageboxs.doubles.*;
import gplx.xowa.wikis.data.*; import gplx.xowa.wikis.data.tbls.*; import gplx.xowa.addons.wikis.ctgs.dbs.*;
public class Xoctg_pagebox_wtr {
private final Xoctg_single_box single_box = new Xoctg_single_box();
private final Xoctg_double_box double_box = new Xoctg_double_box();
private final Xoctg_pagebox_hash hash = new Xoctg_pagebox_hash();
private final Xowd_page_itm tmp_page_itm = new Xowd_page_itm();
public void Init_by_wiki(Xow_wiki wiki) {
single_box.Init_by_wiki(wiki);
double_box.Init_by_wiki(wiki);
}
public void Write_pagebox(boolean double_mode, Bry_bfr bfr, Xow_wiki wiki, Xoa_page page, Xoctg_pagebox_itm[] pagebox_itms) {
try {
if (double_mode)
double_box.Write_pagebox(bfr, pagebox_itms);
else
single_box.Write_pagebox(bfr, pagebox_itms);
} catch (Exception e) {
Gfo_usr_dlg_.Instance.Warn_many("", "", "failed to write pagebox categories; page=~{0} err=~{1}", page.Url_bry_safe(), Err_.Message_gplx_log(e));
}
}
public Xoctg_pagebox_itm[] Get_catlinks_by_page(Xow_wiki wiki, Xoa_page page) {
int wtxt_ctgs_len = page.Wtxt().Ctgs__len();
// html_dbs will always be 0 since they do not parse ctgs; note that wtxt_dbs can also have 0 if no ctgs
if (wtxt_ctgs_len == 0) {
// init
Xoctg_pagebox_loader select_cbk = new Xoctg_pagebox_loader(hash, page.Url_bry_safe());
// get cat_db_id from page
boolean exists = wiki.Data__core_mgr().Tbl__page().Select_by_ttl(tmp_page_itm, page.Ttl().Ns(), page.Ttl().Page_txt());
int cat_db_id = tmp_page_itm.Cat_db_id();
if (exists && cat_db_id != -1) {// note that wtxt_dbs can have 0 ctgs but will have cat_db_id == -1
Xow_db_file cat_link_db = wiki.Data__core_mgr().Dbs__get_by_id_or_null(cat_db_id);
if (cat_link_db != null && Io_mgr.Instance.ExistsFil(cat_link_db.Url())) { // make sure cat_db_id exists
select_cbk.Select_catlinks_by_page(wiki, cat_link_db.Conn(), hash, tmp_page_itm.Id());
}
}
// get hidden
int hash_len = hash.Len();
if (hash_len > 0) { // note that html_dbs may have 0 ctgs in cat_db; don't bother checking cat_core
Xowd_cat_core_tbl cat_core_tbl = Xodb_cat_db_.Get_cat_core_or_fail(wiki.Data__core_mgr());
cat_core_tbl.Select_by_cat_id_many(select_cbk);
}
}
// wtxt_dbs will always have itms;
else {
for (int i = 0; i < wtxt_ctgs_len; ++i) {
Xoa_ttl ttl = page.Wtxt().Ctgs__get_at(i);
hash.Add_by_ttl(ttl);
}
}
return hash.To_ary_and_clear();
}
}

@ -0,0 +1,52 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.htmls.pageboxs.doubles; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*; import gplx.xowa.addons.wikis.ctgs.htmls.pageboxs.*;
import gplx.core.brys.*; import gplx.core.brys.fmts.*; import gplx.core.brys.fmtrs.*;
import gplx.xowa.wikis.data.tbls.*;
import gplx.xowa.htmls.core.htmls.*;
import gplx.xowa.users.history.*;
import gplx.xowa.addons.wikis.ctgs.htmls.*;
public class Xoctg_double_box implements Bfr_arg {
public Xoctg_double_grp Grp_normal() {return grp_normal;} private final Xoctg_double_grp grp_normal = new Xoctg_double_grp();
public Xoctg_double_grp Grp_hidden() {return grp_hidden;} private final Xoctg_double_grp grp_hidden = new Xoctg_double_grp();
public void Init_by_wiki(Xow_wiki wiki) {
Xou_history_mgr history_mgr = wiki.App().User().History_mgr();
grp_normal.Init_by_wiki(wiki, history_mgr, Bool_.Y);
grp_hidden.Init_by_wiki(wiki, history_mgr, Bool_.N);
}
public void Write_pagebox(Bry_bfr bfr, Xoctg_pagebox_itm[] ary) {
grp_normal.Itms().Itms__clear();
grp_hidden.Itms().Itms__clear();
int len = ary.length;
for (int i = 0; i < len; ++i) {
Xoctg_pagebox_itm ctg = ary[i];
Xoctg_double_grp list = ctg.Hidden() ? grp_hidden : grp_normal;
list.Itms().Itms__add(ctg);
}
this.Bfr_arg__add(bfr);
}
public void Bfr_arg__add(Bry_bfr bfr) {
Fmt__all.Bld_many(bfr, grp_normal, grp_hidden);
}
private static final Bry_fmt
Fmt__all = Bry_fmt.Auto_nl_skip_last
( "<div id=\"catlinks\" class=\"catlinks\">~{grp_normal}~{grp_hidden}"
, "</div>"
);
}

@ -15,14 +15,14 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.wikis.ctgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.wikis.*;
package gplx.xowa.addons.wikis.ctgs.htmls.pageboxs.doubles; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*; import gplx.xowa.addons.wikis.ctgs.htmls.pageboxs.*;
import org.junit.*;
import gplx.xowa.wikis.data.tbls.*;
public class Xoctg_pagelist_wtr_tst {
@Before public void init() {fxt.Clear();} private Xoctg_pagelist_mgr_fxt fxt = new Xoctg_pagelist_mgr_fxt();
public class Xoctg_double_box__tst {
@Before public void init() {fxt.Clear();} private Xoctg_double_box__fxt fxt = new Xoctg_double_box__fxt();
@Test public void Basic() {
fxt.Init_ctg_hidden("A", "B", "C");
fxt.Init_ctg_normal("D", "E", "F");
fxt.Init_ctg_hidden("Category:A", "Category:B", "Category:C");
fxt.Init_ctg_normal("Category:D", "Category:E", "Category:F");
fxt.Test_print_hidden(String_.Concat_lines_nl
( "<div id=\"catlinks\" class=\"catlinks\">"
, "<div id=\"mw-normal-catlinks\" class=\"mw-normal-catlinks\">"
@ -56,32 +56,30 @@ public class Xoctg_pagelist_wtr_tst {
));
}
}
class Xoctg_pagelist_mgr_fxt {
class Xoctg_double_box__fxt {
private Xop_fxt fxt; private Xoctg_double_box hidden_wtr;
private final List_adp init_ctgs = List_adp_.New();
public void Clear() {
fxt = new Xop_fxt();
app = fxt.App();
hidden_wtr = new Xoctg_pagelist_wtr();
hidden_wtr.Init_by_app(app);
hidden_wtr = new Xoctg_double_box();
hidden_wtr.Init_by_wiki(fxt.Wiki());
init_ctgs.Clear();
} private Xop_fxt fxt; private Xoae_app app; private Xoctg_pagelist_wtr hidden_wtr;
}
public void Init_ctg_normal(String... ary) {Init_ctg(Bool_.N, ary);}
public void Init_ctg_hidden(String... ary) {Init_ctg(Bool_.Y, ary);}
public void Init_ctg(boolean hidden, String[] ary) {
int len = ary.length;
for (int i = 0; i < len; i++) {
String ttl = ary[i];
Xowd_page_itm page = new Xowd_page_itm();
Xowd_category_itm ctg_xtn = Xowd_category_itm.load_(0, 0, hidden, 0, 0, 0);
page.Xtn_(ctg_xtn);
page.Ttl_page_db_(Bry_.new_a7(ttl));
init_ctgs.Add_many(page);
Xoa_ttl ttl = fxt.Wiki().Ttl_parse(Bry_.new_u8(ary[i]));
Xoctg_pagebox_itm itm = Xoctg_pagebox_itm.New_by_ttl(ttl);
itm.Load_by_cat_core(hidden, 0, 0, 0);
init_ctgs.Add_many(itm);
}
} private List_adp init_ctgs = List_adp_.New();
}
public void Test_print_hidden(String expd) {
Bry_bfr bfr = Bry_bfr_.New();
Xowd_page_itm[] page_ary = (Xowd_page_itm[])init_ctgs.To_ary_and_clear(Xowd_page_itm.class);
hidden_wtr.Print_hidden(bfr, fxt.Wiki(), page_ary, gplx.xowa.htmls.core.htmls.Xoh_wtr_ctx.Basic);
Xoctg_pagebox_itm[] ary = (Xoctg_pagebox_itm[])init_ctgs.To_ary_and_clear(Xoctg_pagebox_itm.class);
hidden_wtr.Write_pagebox(bfr, ary);
Tfds.Eq_str_lines(expd, bfr.To_str_and_clear());
// Tfds.Dbg(bfr.To_bry_and_clear());
}
}

@ -0,0 +1,58 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.htmls.pageboxs.doubles; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*; import gplx.xowa.addons.wikis.ctgs.htmls.pageboxs.*;
import gplx.core.brys.*; import gplx.core.brys.fmts.*;
import gplx.xowa.langs.*; import gplx.xowa.langs.msgs.*;
import gplx.xowa.htmls.core.htmls.*;
import gplx.xowa.users.history.*;
public class Xoctg_double_grp implements Bfr_arg {
private byte[] lbl_ctg_help, lbl_ctg_text, lbl_hidden;
public boolean Type_is_normal() {return type_is_normal;} private boolean type_is_normal;
public Xoctg_double_itm Itms() {return itms;} private final Xoctg_double_itm itms = new Xoctg_double_itm();
public void Init_by_wiki(Xow_wiki wiki, Xou_history_mgr history_mgr, boolean type_is_normal) {
this.type_is_normal = type_is_normal;
lbl_ctg_text = wiki.Msg_mgr().Val_by_id(Xol_msg_itm_.Id_ctg_tbl_hdr);
lbl_ctg_help = Xol_msg_mgr_.Get_msg_val(wiki, wiki.Lang(), Key_pagecategorieslink, Bry_.Ary_empty);
lbl_hidden = wiki.Msg_mgr().Val_by_id(Xol_msg_itm_.Id_ctg_tbl_hidden);
itms.Init_by_wiki(wiki, history_mgr);
}
public void Bfr_arg__add(Bry_bfr bfr) {
if (type_is_normal)
Fmt__normal.Bld_many(bfr, lbl_ctg_help, lbl_ctg_text, itms);
else
Fmt__hidden.Bld_many(bfr, lbl_hidden, itms);
}
private static final byte[] Key_pagecategorieslink = Bry_.new_a7("pagecategorieslink");
private static final Bry_fmt
Fmt__normal = Bry_fmt.Auto_nl_skip_last
( ""
, "<div id=\"mw-normal-catlinks\" class=\"mw-normal-catlinks\">"
, "<a href=\"/wiki/~{ctg_help_page}\" title=\"~{ctg_help_page}\">~{ctg_text}</a>:"
, "<ul>~{grp_itms}"
, "</ul>"
, "</div>"
)
, Fmt__hidden = Bry_fmt.Auto_nl_skip_last
( ""
, "<div id=\"mw-hidden-catlinks\" class=\"mw-hidden-catlinks mw-hidden-cats-user-shown\">~{hidden_ctg_txt}:"
, "<ul>~{grp_itms}"
, "</ul>"
, "</div>"
);
}

@ -0,0 +1,60 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.htmls.pageboxs.doubles; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*; import gplx.xowa.addons.wikis.ctgs.htmls.pageboxs.*;
import gplx.core.brys.fmts.*; import gplx.core.brys.fmtrs.*;
import gplx.xowa.htmls.*; import gplx.xowa.htmls.hrefs.*; import gplx.xowa.htmls.core.htmls.*; import gplx.xowa.htmls.core.wkrs.lnkis.htmls.*;
import gplx.xowa.wikis.nss.*;
import gplx.xowa.users.history.*;
public class Xoctg_double_itm implements gplx.core.brys.Bfr_arg {
private final List_adp itms = List_adp_.New();
private Xow_wiki wiki; private Xoh_href_wtr href_wtr; private Xou_history_mgr history_mgr;
public void Init_by_wiki(Xow_wiki wiki, Xou_history_mgr history_mgr) {
this.wiki = wiki;
this.href_wtr = wiki.Html__href_wtr();
this.history_mgr = history_mgr;
}
public void Itms__clear() {itms.Clear();}
public void Itms__add(Xoctg_pagebox_itm page) {itms.Add(page);}
public void Bfr_arg__add(Bry_bfr bfr) {
int len = itms.Count();
for (int i = 0; i < len; ++i) {
Xoctg_pagebox_itm itm = (Xoctg_pagebox_itm)itms.Get_at(i);
Xoa_ttl ttl = itm.Ttl();
byte[] lnki_cls = Xoh_lnki_wtr.Lnki_cls_visited(history_mgr, wiki.Domain_bry(), ttl.Page_txt());// NOTE: must be ttl.Page_txt() in order to match Xou_history_mgr.Add
byte[] lnki_href = href_wtr.Build_to_bry(wiki, ttl);
byte[] lnki_text = ttl.Page_txt();
byte[] lnki_ttl = ttl.Full_txt_w_ttl_case();
// build title
// tmp_bfr.Add(ttl.Full_txt_w_ttl_case());
// tmp_bfr.Add_byte_space().Add_byte(Byte_ascii.Paren_bgn) .Add_byte(Byte_ascii.Ltr_S).Add_byte_colon().Add_int_variable(itm.Count__subcs());
// tmp_bfr.Add_byte_space().Add_byte(Byte_ascii.Comma) .Add_byte(Byte_ascii.Ltr_P).Add_byte_colon().Add_int_variable(itm.Count__pages());
// tmp_bfr.Add_byte_space().Add_byte(Byte_ascii.Comma) .Add_byte(Byte_ascii.Ltr_F).Add_byte_colon().Add_int_variable(itm.Count__files());
// tmp_bfr.Add_byte(Byte_ascii.Paren_end);
// byte[] lnki_ttl = tmp_bfr.To_bry_and_clear();
Fmt__itm.Bld_many(bfr, lnki_cls, lnki_href, lnki_ttl, lnki_text);
}
}
private static final Bry_fmt Fmt__itm = Bry_fmt.Auto_nl_skip_last
( ""
, "<li>"
, "<a~{lnki_cls} href=\"~{lnki_href}\" title=\"~{lnki_ttl}\">~{lnki_text}</a>"
, "</li>"
);
}

@ -0,0 +1,42 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.htmls.pageboxs.singles; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*; import gplx.xowa.addons.wikis.ctgs.htmls.pageboxs.*;
import gplx.core.brys.*; import gplx.core.brys.fmts.*; import gplx.core.brys.fmtrs.*;
import gplx.xowa.langs.*; import gplx.xowa.langs.msgs.*;
import gplx.xowa.htmls.core.htmls.*;
public class Xoctg_single_box {
private final Xoctg_single_itm itms_fmtr = new Xoctg_single_itm();
private byte[] lbl_categories;
public void Init_by_wiki(Xow_wiki wiki) {
this.lbl_categories = wiki.Msg_mgr().Val_by_id(Xol_msg_itm_.Id_ctg_tbl_hdr);
itms_fmtr.Init_by_wiki(wiki);
}
public void Write_pagebox(Bry_bfr bfr, Xoctg_pagebox_itm[] itms) {
itms_fmtr.Init_by_page(itms);
Fmt__grp.Bld_many(bfr, lbl_categories, itms_fmtr);
}
private static final Bry_fmt Fmt__grp = Bry_fmt.Auto_nl_skip_last
( "<div id=\"catlinks\" class=\"catlinks\">"
, "<div id=\"mw-normal-catlinks\" class=\"mw-normal-catlinks\">"
, "~{grp_lbl}"
, "<ul>~{grp_itms}"
, "</ul>"
, "</div>"
, "</div>"
);
}

@ -15,13 +15,13 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.htmls; import gplx.*; import gplx.xowa.*;
package gplx.xowa.addons.wikis.ctgs.htmls.pageboxs.singles; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*; import gplx.xowa.addons.wikis.ctgs.htmls.pageboxs.*;
import org.junit.*;
public class Xohp_ctg_grp_mgr_tst {
Xoh_ctg_mgr_fxt fxt = new Xoh_ctg_mgr_fxt();
@Before public void init() {fxt.Clear();}
import gplx.xowa.htmls.core.htmls.*;
public class Xoctg_single_box__tst {
@Before public void init() {fxt.Clear();} private final Xoh_ctg_mgr_fxt fxt = new Xoh_ctg_mgr_fxt();
@Test public void Basic() {
fxt.Init_ctgs("A", "B").Test_html(String_.Concat_lines_nl
fxt.Init__ctgs("Category:A", "Category:B").Test_html(String_.Concat_lines_nl
( "<div id=\"catlinks\" class=\"catlinks\">"
, "<div id=\"mw-normal-catlinks\" class=\"mw-normal-catlinks\">"
, "Categories"
@ -39,18 +39,24 @@ public class Xohp_ctg_grp_mgr_tst {
}
}
class Xoh_ctg_mgr_fxt {
public Xoh_ctg_mgr_fxt Clear() {
private Xoctg_single_box ctg_grp_mgr; Xoae_app app; Xowe_wiki wiki; Bry_bfr tmp_bfr = Bry_bfr_.New();
private Xoae_page page;
public void Clear() {
app = Xoa_app_fxt.Make__app__edit();
wiki = Xoa_app_fxt.Make__wiki__edit(app);
ctg_grp_mgr = new Xohp_ctg_grp_mgr();
page = wiki.Parser_mgr().Ctx().Page();
ctg_grp_mgr = new Xoctg_single_box();
ctg_grp_mgr.Init_by_wiki(wiki);
}
public Xoh_ctg_mgr_fxt Init__ctgs(String... ary) {
int len = ary.length;
for (int i = 0; i < len; ++i) {
page.Wtxt().Ctgs__add(wiki.Ttl_parse(Bry_.new_u8(ary[i])));
}
return this;
} private Xohp_ctg_grp_mgr ctg_grp_mgr; Xoae_app app; Xowe_wiki wiki; Bry_bfr tmp_bfr = Bry_bfr_.New();
public Xoh_ctg_mgr_fxt Init_ctgs(String... v) {init_ctgs = v; return this;} private String[] init_ctgs;
}
public void Test_html(String expd) {
byte[][] ctgs_bry_ary = Bry_.Ary(init_ctgs);
Xoae_page page = wiki.Parser_mgr().Ctx().Page();
page.Category_list_(ctgs_bry_ary);
ctg_grp_mgr.Bld(tmp_bfr, page, ctgs_bry_ary.length);
ctg_grp_mgr.Write_pagebox(tmp_bfr, Xoctg_pagebox_itm.New_ary(page));
Tfds.Eq_str_lines(expd, tmp_bfr.To_str_and_clear());
}
}

@ -0,0 +1,41 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.ctgs.htmls.pageboxs.singles; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.ctgs.*; import gplx.xowa.addons.wikis.ctgs.htmls.*; import gplx.xowa.addons.wikis.ctgs.htmls.pageboxs.*;
import gplx.core.brys.*; import gplx.core.brys.fmts.*;
class Xoctg_single_itm implements Bfr_arg {
private final Bry_bfr tmp_bfr = Bry_bfr_.New();
private Xow_wiki wiki;
private Xoctg_pagebox_itm[] itms;
public void Init_by_wiki(Xow_wiki wiki) {this.wiki = wiki;}
public void Init_by_page(Xoctg_pagebox_itm[] itms) {this.itms = itms;}
public void Bfr_arg__add(Bry_bfr bfr) {
int len = itms.length;
for (int i = 0; i < len; ++i) {
Xoa_ttl ctg_ttl = itms[i].Ttl();
wiki.Html__href_wtr().Build_to_bfr(tmp_bfr, wiki.App(), wiki.Domain_bry(), ctg_ttl);
byte[] ctg_page_txt = ctg_ttl.Page_txt();
Fmt__itm.Bld_many(bfr, tmp_bfr.To_bry_and_clear(), ctg_page_txt, ctg_page_txt);
}
}
private static final Bry_fmt Fmt__itm = Bry_fmt.Auto_nl_skip_last
( ""
, "<li>"
, "<a href=\"~{itm_href}\" class=\"internal\" title=\"~{itm_title}\">~{itm_text}</a>"
, "</li>"
);
}

@ -19,17 +19,17 @@ package gplx.xowa.addons.wikis.pages.syncs; import gplx.*; import gplx.xowa.*; i
import gplx.xowa.bldrs.wkrs.*;
import gplx.xowa.specials.*;
import gplx.xowa.addons.wikis.pages.syncs.specials.*;
public class Sync_addon implements Xoax_addon_itm, Xoax_addon_itm__special {
public class Xosync_addon implements Xoax_addon_itm, Xoax_addon_itm__special {
public Xow_special_page[] Special_pages() {
return new Xow_special_page[]
{ Sync_html_special.Prototype
};
}
public static Sync_addon Get(Xow_wiki wiki) {
Sync_addon rv = (Sync_addon)wiki.Addon_mgr().Itms__get_or_null(ADDON_KEY);
public static Xosync_addon Get(Xow_wiki wiki) {
Xosync_addon rv = (Xosync_addon)wiki.Addon_mgr().Itms__get_or_null(ADDON_KEY);
if (rv == null) {
rv = new Sync_addon();
rv = new Xosync_addon();
wiki.Addon_mgr().Itms__add(rv);
}
return rv;

@ -0,0 +1,55 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.pages.syncs.core; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.syncs.*;
import gplx.dbs.*;
import gplx.xowa.htmls.*;
import gplx.xowa.addons.wikis.pages.syncs.dbs.*;
import gplx.xowa.apps.apis.xowa.addons.bldrs.*;
import gplx.xowa.wikis.data.tbls.*;
public class Xosync_read_mgr {
private final Xowd_page_itm tmp_dbpg = new Xowd_page_itm();
private Db_conn sync_conn; private Xosync_sync_tbl sync_tbl;
private final Xosync_update_mgr update_mgr = new Xosync_update_mgr();
public void Auto_update(Xow_wiki wiki, Xoa_page page, Xoa_ttl page_ttl) {
if (wiki.Domain_itm().Domain_type_id() == gplx.xowa.wikis.domains.Xow_domain_tid_.Tid__home) return;
if (page_ttl.Ns().Id_is_special()) return;
Xoapi_sync_api sync_api = wiki.App().Api_root().Addon().Bldr().Sync();
if (!sync_api.Auto_enabled()) return;
if (!sync_api.Auto_page_matcher().Match(page_ttl.Full_db())) return;
wiki.Data__core_mgr().Db__core().Tbl__page().Select_by_ttl(tmp_dbpg, page_ttl.Ns(), page_ttl.Page_db());
if (sync_conn == null) {
Io_url sync_db_url = wiki.Fsys_mgr().Root_dir().GenSubFil(wiki.Domain_str() + "-sync.xowa");
sync_conn = Db_conn_bldr.Instance.Get_or_autocreate(true, sync_db_url);
sync_tbl = new Xosync_sync_tbl(sync_conn);
sync_conn.Meta_tbl_assert(sync_tbl);
}
DateAdp sync_date = sync_tbl.Select_sync_date_or_min(tmp_dbpg.Id());
if (Datetime_now.Get().Diff(sync_date).Total_mins().To_int() < sync_api.Auto_interval()) return;
Xoa_app app = wiki.App();
Xoh_page hpg = new Xoh_page();
update_mgr.Init_by_app(app);
update_mgr.Init_by_page(wiki, hpg);
update_mgr.Update(app.Wmf_mgr().Download_wkr(), wiki, page_ttl);
sync_tbl.Upsert(tmp_dbpg.Id(), Datetime_now.Get());
}
}

@ -15,21 +15,23 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.apps.wms.apis.parses; import gplx.*; import gplx.xowa.*; import gplx.xowa.apps.*; import gplx.xowa.apps.wms.*; import gplx.xowa.apps.wms.apis.*;
package gplx.xowa.addons.wikis.pages.syncs.core; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.syncs.*;
import gplx.xowa.files.downloads.*;
import gplx.xowa.wikis.data.*;
import gplx.xowa.htmls.*; import gplx.langs.htmls.docs.*;
import gplx.xowa.htmls.core.wkrs.*; import gplx.xowa.htmls.core.wkrs.txts.*; import gplx.xowa.htmls.core.hzips.*;
import gplx.xowa.htmls.core.dbs.*;
public class Wm_page_updater {
import gplx.xowa.addons.wikis.pages.syncs.wmapis.*;
import gplx.xowa.addons.wikis.pages.syncs.core.parsers.*;
public class Xosync_update_mgr {
private final Xoh_hzip_bfr bfr = new Xoh_hzip_bfr(Io_mgr.Len_mb, Bool_.N, Byte_.Max_value_127);
private final Gfh_doc_parser hdoc_parser_mgr;
private final Xoh_hdoc_ctx hctx = new Xoh_hdoc_ctx();
private final Wm_hdoc_bldr hdoc_bldr = new Wm_hdoc_bldr();
private final Wm_hdoc_parser_wkr hdoc_parser_wkr;
private final Xosync_hdoc_wtr hdoc_bldr = new Xosync_hdoc_wtr();
private final Xosync_hdoc_parser hdoc_parser_wkr;
private final Xowd_html_tbl_mgr html_tbl_mgr = new Xowd_html_tbl_mgr();
public Wm_page_updater() {
hdoc_parser_wkr = new Wm_hdoc_parser_wkr(hdoc_bldr);
public Xosync_update_mgr() {
hdoc_parser_wkr = new Xosync_hdoc_parser(hdoc_bldr);
hdoc_parser_mgr = new Gfh_doc_parser(new Xoh_txt_parser(hdoc_bldr), hdoc_parser_wkr);
}
public void Init_by_app(Xoa_app app) {
@ -43,7 +45,7 @@ public class Wm_page_updater {
Xoh_page hpg = (Xoh_page)hctx.Page();
// call wmf api
Xowm_parse_base parse_wkr = new Xowm_parse_wmf();
Xowm_parse_wmf parse_wkr = new Xowm_parse_wmf();
Xowm_parse_data data = parse_wkr.Get_parse_or_null(download_wkr, wiki, page_ttl);
if (data == null) return;

@ -0,0 +1,79 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.wikis.pages.syncs.core.loaders; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.syncs.*; import gplx.xowa.addons.wikis.pages.syncs.core.*;
import gplx.core.brys.*;
import gplx.langs.htmls.*; import gplx.xowa.htmls.*; import gplx.langs.htmls.docs.*; import gplx.xowa.htmls.core.wkrs.*; import gplx.xowa.htmls.core.wkrs.imgs.atrs.*;
import gplx.xowa.files.*; import gplx.xowa.files.repos.*;
import gplx.xowa.wikis.domains.*;
import gplx.xowa.addons.wikis.pages.syncs.core.parsers.*;
public class Xosync_page_loader {
private final Xoh_hdoc_ctx hctx = new Xoh_hdoc_ctx();
private final Gfh_tag_rdr tag_rdr = Gfh_tag_rdr.New__html();
private final Bry_err_wkr err_wkr = new Bry_err_wkr();
private final Xoh_img_src_data img_src_parser = new Xoh_img_src_data();
private final Bry_bfr tmp_bfr = Bry_bfr_.New();
public byte[] Parse(Xow_wiki wiki, Xoh_page hpg, byte[] src) {
// init hctx, tag_rdr, err_wkr
int src_len = src.length;
hctx.Init_by_page(wiki, hpg);
tag_rdr.Init(hpg.Url_bry_safe(), src, 0, src_len);
err_wkr.Init_by_page(String_.new_u8(hpg.Url_bry_safe()), src);
// loop for all <img>
int pos = 0;
while (true) {
// get next "<img>"
Gfh_tag img_tag = tag_rdr.Tag__find_fwd_head(pos, src_len, Gfh_tag_.Id__img);
// none found; add and exit
if (img_tag.Name_id() == Gfh_tag_.Id__eos) {
tmp_bfr.Add_mid(src, pos, src_len); // add bytes between img_end and prv_pos
break;
}
// add bytes between prv_pos and img_bgn
tmp_bfr.Add_mid(src, pos, img_tag.Src_bgn());
// do simple replace for @src
Gfh_atr img_src_atr = img_tag.Atrs__get_by_or_fail(Gfh_atr_.Bry__src);
byte[] img_src_val = img_src_atr.Val();
img_src_val = Bry_.Replace(img_src_val, Xosync_img_src_parser.Bry__xowa_src_bgn, wiki.App().Fsys_mgr().File_dir().To_http_file_bry());
// parse other atrs for fsdb
img_src_parser.Parse(err_wkr, hctx, wiki.Domain_bry(), img_src_atr.Val_bgn(), img_src_atr.Val_end());
if (img_src_parser.File_ttl_bry() != null) { // NOTE: need to skip images that don't follow MW image format ("commons.wikimedia.org/thumb/7/70/A.png"); for example, math images
Xof_fsdb_itm img = hpg.Img_mgr().Make_img(false);
byte[] file_ttl_bry = gplx.langs.htmls.encoders.Gfo_url_encoder_.Http_url.Decode(img_src_parser.File_ttl_bry());
img.Init_by_wm_parse(hctx.Wiki__domain_itm().Abrv_xo(), img_src_parser.Repo_is_commons(), img_src_parser.File_is_orig(), file_ttl_bry, img_src_parser.File_w(), img_src_parser.File_time(), img_src_parser.File_page());
hctx.File__url_bldr().Init_by_root(img_src_parser.Repo_is_commons() ? hctx.Fsys__file__comm() : hctx.Fsys__file__wiki(), Bool_.N, Byte_ascii.Slash, Bool_.N, Bool_.N, 4);
hctx.File__url_bldr().Init_by_itm(img_src_parser.File_is_orig() ? Xof_repo_itm_.Mode_orig : Xof_repo_itm_.Mode_thumb, file_ttl_bry, Xof_file_wkr_.Md5(file_ttl_bry), Xof_ext_.new_by_ttl_(file_ttl_bry), img_src_parser.File_w(), img_src_parser.File_time(), img_src_parser.File_page());
img.Orig_repo_name_(img_src_parser.Repo_is_commons() ? Xow_domain_itm_.Bry__commons : wiki.Domain_bry());
Io_url html_view_url = hctx.File__url_bldr().Xto_url_by_http();
img.Init_at_gallery_end(img_tag.Atrs__get_as_int(Gfh_atr_.Bry__width), img_tag.Atrs__get_as_int(Gfh_atr_.Bry__height), html_view_url, html_view_url);
Xosync_hdoc_parser.Write_img_tag(tmp_bfr, img_tag, img_src_val, img.Html_uid());
}
pos = img_tag.Src_end();
}
// overwrite html
src = tmp_bfr.To_bry_and_clear();
hpg.Db().Html().Html_bry_(src);
return src;
}
}

@ -15,12 +15,13 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.apps.wms.apis.parses; import gplx.*; import gplx.xowa.*; import gplx.xowa.apps.*; import gplx.xowa.apps.wms.*; import gplx.xowa.apps.wms.apis.*;
package gplx.xowa.addons.wikis.pages.syncs.core.loaders; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.syncs.*; import gplx.xowa.addons.wikis.pages.syncs.core.*;
import gplx.core.tests.*;
import gplx.langs.htmls.*; import gplx.xowa.htmls.*;
import gplx.xowa.files.*; import gplx.xowa.files.repos.*;
class Wm_page_loader_fxt {
private final Wm_page_loader mgr = new Wm_page_loader();
import gplx.xowa.addons.wikis.pages.syncs.core.parsers.*;
public class Xosync_page_loader__fxt {
private final Xosync_page_loader mgr = new Xosync_page_loader();
private final Bry_bfr tmp_bfr = Bry_bfr_.New();
private final Xoh_page hpg = new Xoh_page();
private Xowe_wiki wiki;
@ -29,11 +30,11 @@ class Wm_page_loader_fxt {
this.wiki = Xoa_app_fxt.Make__wiki__edit(app);
hpg.Clear();
}
public Wm_page_loader_fxt Exec__parse(String raw) {
public Xosync_page_loader__fxt Exec__parse(String raw) {
mgr.Parse(wiki, hpg, Bry_.new_u8(raw));
return this;
}
public Wm_page_loader_fxt Test__html(String expd) {
public Xosync_page_loader__fxt Test__html(String expd) {
Gftest.Eq__ary__lines(expd, hpg.Db().Html().Html_bry(), "converted html");
return this;
}
@ -42,9 +43,9 @@ class Wm_page_loader_fxt {
itm.Init_by_wm_parse(wiki.Domain_itm().Abrv_xo(), repo_is_commons, file_is_thumb, Bry_.new_u8(file_ttl), file_w, file_time, file_page);
return itm;
}
public Wm_page_loader_fxt Test__fsdb(Xof_fsdb_itm expd) {
public Xosync_page_loader__fxt Test__fsdb(Xof_fsdb_itm expd) {
Xof_fsdb_itm actl = (Xof_fsdb_itm)hpg.Img_mgr().Get_at(0);
Gftest.Eq__str(Xowm_parse_mgr_fxt.To_str(tmp_bfr, expd), Xowm_parse_mgr_fxt.To_str(tmp_bfr, actl));
Gftest.Eq__str(Xosync_hdoc_parser__fxt.To_str(tmp_bfr, expd), Xosync_hdoc_parser__fxt.To_str(tmp_bfr, actl));
return this;
}
}

@ -15,14 +15,14 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.apps.wms.apis.parses; import gplx.*; import gplx.xowa.*; import gplx.xowa.apps.*; import gplx.xowa.apps.wms.*; import gplx.xowa.apps.wms.apis.*;
package gplx.xowa.addons.wikis.pages.syncs.core.loaders; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.syncs.*; import gplx.xowa.addons.wikis.pages.syncs.core.*;
import org.junit.*;
import gplx.langs.htmls.*;
public class Wm_page_loader_tst {
@Before public void init() {fxt.Clear();} private final Wm_page_loader_fxt fxt = new Wm_page_loader_fxt();
public class Xosync_page_loader__tst {
@Before public void init() {fxt.Clear();} private final Xosync_page_loader__fxt fxt = new Xosync_page_loader__fxt();
@Test public void Basic() {
fxt.Exec__parse(Gfh_utl.Replace_apos("a<img src='xowa:/file/commons.wikimedia.org/thumb/4/a/6/9/Commons-logo.svg/12px.png'>b"))
.Test__html(Gfh_utl.Replace_apos("a<img src='file:///mem/xowa/file/commons.wikimedia.org/thumb/4/a/6/9/Commons-logo.svg/12px.png'>b"))
fxt.Exec__parse(Gfh_utl.Replace_apos("a<img src='xowa:/file/commons.wikimedia.org/thumb/4/a/6/9/Commons-logo.svg/12px.png' width='12' height='20'>b"))
.Test__html(Gfh_utl.Replace_apos("a<img id='xoimg_0' src='file:///mem/xowa/file/commons.wikimedia.org/thumb/4/a/6/9/Commons-logo.svg/12px.png' width='12' height='20'>b"))
.Test__fsdb(fxt.Make__fsdb(Bool_.Y, Bool_.N, "Commons-logo.svg", 12, -1, -1))
;
}

@ -15,24 +15,37 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.apps.wms.apis.parses; import gplx.*; import gplx.xowa.*; import gplx.xowa.apps.*; import gplx.xowa.apps.wms.*; import gplx.xowa.apps.wms.apis.*;
package gplx.xowa.addons.wikis.pages.syncs.core.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.syncs.*; import gplx.xowa.addons.wikis.pages.syncs.core.*;
import gplx.langs.htmls.*; import gplx.langs.htmls.docs.*; import gplx.xowa.htmls.core.wkrs.*;
class Wm_hdoc_parser_wkr implements Gfh_doc_wkr {
private final Wm_hdoc_bldr hdoc_wkr;
public class Xosync_hdoc_parser implements Gfh_doc_wkr {
private final Xosync_hdoc_wtr hdoc_wtr;
private final Gfh_tag_rdr tag_rdr = Gfh_tag_rdr.New__html();
private final Bry_bfr tmp_bfr = Bry_bfr_.New();
private final Wm_img_src_parser img_src_data = new Wm_img_src_parser();
private final Xosync_img_src_parser img_src_parser = new Xosync_img_src_parser();
public Wm_hdoc_parser_wkr(Wm_hdoc_bldr hdoc_wkr) {this.hdoc_wkr = hdoc_wkr;}
public Xosync_hdoc_parser(Xosync_hdoc_wtr hdoc_wtr) {this.hdoc_wtr = hdoc_wtr;}
public byte[] Hook() {return Byte_ascii.Angle_bgn_bry;}
public void Init_by_page(Xoh_hdoc_ctx hctx, byte[] src, int src_bgn, int src_end) {
tag_rdr.Init(hctx.Page__url(), src, src_bgn, src_end);
img_src_data.Init_by_page(hctx);
img_src_parser.Init_by_page(hctx);
}
public int Parse(byte[] src, int src_bgn, int src_end, int pos) {
// note that entry point is at "<"
tag_rdr.Pos_(pos);
int nxt_pos = tag_rdr.Pos() + 1; if (nxt_pos == src_end) return src_end;
Gfh_tag cur = src[tag_rdr.Pos() + 1] == Byte_ascii.Slash ? tag_rdr.Tag__move_fwd_tail(Gfh_tag_.Id__any) : tag_rdr.Tag__move_fwd_head();
// check if head or tail; EX: "<a>" vs "</a>"
byte nxt_byte = src[nxt_pos];
// skip comment; needed else comment may gobble up rest of text; see test; DATE:2016-09-10
if (nxt_byte == Byte_ascii.Bang) { // assume comment; EX:"<!--"
int end_comm = Bry_find_.Move_fwd(src, Gfh_tag_.Comm_end, nxt_pos);
if (end_comm == Bry_find_.Not_found) {
Gfo_usr_dlg_.Instance.Warn_many("", "", "end comment not found; src=~{0}", String_.new_u8(src));
end_comm = src_end;
}
return end_comm;
}
Gfh_tag cur = nxt_byte == Byte_ascii.Slash ? tag_rdr.Tag__move_fwd_tail(Gfh_tag_.Id__any) : tag_rdr.Tag__move_fwd_head();
if (cur.Tag_is_tail()) {}
else {
int cur_name_id = cur.Name_id();
@ -42,48 +55,49 @@ class Wm_hdoc_parser_wkr implements Gfh_doc_wkr {
tag_rdr.Tag__move_fwd_tail(cur_name_id);
return tag_rdr.Pos();
}
else {
}
break;
case Gfh_tag_.Id__img: // rewrite src for XOWA, particularly to handle relative protocol; EX: "//upload.wikimedia.org"; note do not use <super> tag b/c of issues with anchors like "href=#section"
case Gfh_tag_.Id__img: // rewrite src for XOWA; especially necessary for relative protocol; EX: "//upload.wikimedia.org"; note do not use <super> tag b/c of issues with anchors like "href=#section"
return Parse_img_src(cur);
default:
break;
}
}
hdoc_wkr.On_txt(cur.Src_bgn(), cur.Src_end());
hdoc_wtr.On_txt(cur.Src_bgn(), cur.Src_end());
return cur.Src_end();
}
private int Parse_img_src(Gfh_tag img_tag) {
// get @src and parse it
Gfh_atr src_atr = img_tag.Atrs__get_by_or_empty(Gfh_atr_.Bry__src);
img_src_data.Parse(src_atr.Val());
img_src_parser.Parse(src_atr.Val());
// if error, write comment; EX: <!--error--><img ...>
String err_msg = img_src_data.Err_msg();
String err_msg = img_src_parser.Err_msg();
if (err_msg != null) {
hdoc_wkr.Add_bry(Gfh_tag_.Comm_bgn);
hdoc_wkr.Add_str(img_src_data.Err_msg());
hdoc_wkr.Add_bry(Gfh_tag_.Comm_end);
hdoc_wtr.Add_bry(Gfh_tag_.Comm_bgn);
hdoc_wtr.Add_str(img_src_parser.Err_msg());
hdoc_wtr.Add_bry(Gfh_tag_.Comm_end);
}
// get img_src; use img_src_data if no error, else use original value
byte[] img_src_val = err_msg == null ? img_src_data.To_bry() : src_atr.Val();
// get img_src; use img_src_parser if no error, else use original value
byte[] img_src_val = err_msg == null ? img_src_parser.To_bry() : src_atr.Val();
// write html
Write_img_tag(tmp_bfr, img_tag, img_src_val);
hdoc_wkr.Add_bfr(tmp_bfr);
Write_img_tag(tmp_bfr, img_tag, img_src_val, -1);
hdoc_wtr.Add_bfr(tmp_bfr);
return img_tag.Src_end();
}
public static void Write_img_tag(Bry_bfr bfr, Gfh_tag img_tag, byte[] img_src_val) {
// now, rewrite <img> tag
public static void Write_img_tag(Bry_bfr bfr, Gfh_tag img_tag, byte[] img_src_val, int uid) {
// rewrite <img> tag with custom img_src_val
int atrs_len = img_tag.Atrs__len();
bfr.Add(Byte_ascii.Angle_bgn_bry);
bfr.Add(Gfh_tag_.Bry__img);
if (uid != -1) {
Gfh_atr_.Add(bfr, Gfh_atr_.Bry__id, Bry_.new_a7("xoimg_" + Int_.To_str(uid)));
}
for (int i = 0; i < atrs_len; ++i) {
Gfh_atr atr = img_tag.Atrs__get_at(i);
// rewrite if atr is src; EX: ' src="//upload.wikimedia.org/..."' -> ' src="xowa:/file/..."
// if atr is src use img_src_val; EX: ' src="//upload.wikimedia.org/..."' -> ' src="xowa:/file/..."
Gfh_atr_.Add(bfr, atr.Key(), Bry_.Eq(atr.Key(), Gfh_atr_.Bry__src) ? img_src_val : atr.Val());
}
bfr.Add(Byte_ascii.Angle_end_bry);

@ -15,11 +15,11 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.apps.wms.apis.parses; import gplx.*; import gplx.xowa.*; import gplx.xowa.apps.*; import gplx.xowa.apps.wms.*; import gplx.xowa.apps.wms.apis.*;
package gplx.xowa.addons.wikis.pages.syncs.core.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.syncs.*; import gplx.xowa.addons.wikis.pages.syncs.core.*;
import org.junit.*;
import gplx.langs.htmls.*;
public class Xowm_parse_mgr__err__tst {
@Before public void init() {fxt.Clear();} private final Xowm_parse_mgr_fxt fxt = new Xowm_parse_mgr_fxt();
public class Xosync_hdoc_parser__err__tst {
@Before public void init() {fxt.Clear();} private final Xosync_hdoc_parser__fxt fxt = new Xosync_hdoc_parser__fxt();
@Test public void Url_does_not_start_with_upload_wikimedia_org() {
fxt.Exec__parse(Gfh_utl.Replace_apos("<img src='//fail/wikipedia/commons/thumb/7/70/A.png/220px-A.png'>"))
.Test__html(Gfh_utl.Replace_apos("<!--wm.parse:url does not start with //upload.wikimedia.org--><img src='//fail/wikipedia/commons/thumb/7/70/A.png/220px-A.png'>"));
@ -40,4 +40,8 @@ public class Xowm_parse_mgr__err__tst {
fxt.Exec__parse(Gfh_utl.Replace_apos("<img src='//upload.wikimedia.org/wikipedia/commons/thumb/7/70/A.png/220_fail_px-A.png'>"))
.Test__html(Gfh_utl.Replace_apos("<!--wm.parse:invalid file_w--><img src='//upload.wikimedia.org/wikipedia/commons/thumb/7/70/A.png/220_fail_px-A.png'>"));
}
@Test public void Comment() {
fxt.Exec__parse(Gfh_utl.Replace_apos("<i>a<!-- - --></i><b>b</b><i>c</i>"))
.Test__html(Gfh_utl.Replace_apos("<i>a</i><b>b</b><i>c</i>"));
}
}

@ -15,11 +15,11 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.apps.wms.apis.parses; import gplx.*; import gplx.xowa.*; import gplx.xowa.apps.*; import gplx.xowa.apps.wms.*; import gplx.xowa.apps.wms.apis.*;
package gplx.xowa.addons.wikis.pages.syncs.core.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.syncs.*; import gplx.xowa.addons.wikis.pages.syncs.core.*;
import org.junit.*;
import gplx.langs.htmls.*;
public class Xowm_parse_mgr__file__tst {
@Before public void init() {fxt.Clear();} private final Xowm_parse_mgr_fxt fxt = new Xowm_parse_mgr_fxt();
public class Xosync_hdoc_parser__file__tst {
@Before public void init() {fxt.Clear();} private final Xosync_hdoc_parser__fxt fxt = new Xosync_hdoc_parser__fxt();
@Test public void Commons__thumb() {
fxt.Exec__parse(Gfh_utl.Replace_apos("<img src='//upload.wikimedia.org/wikipedia/commons/thumb/7/70/A.png/220px-A.png'>"))
.Test__html(Gfh_utl.Replace_apos("<img src='xowa:/file/commons.wikimedia.org/thumb/7/0/1/c/A.png/220px.png'>"))

@ -15,12 +15,12 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.apps.wms.apis.parses; import gplx.*; import gplx.xowa.*; import gplx.xowa.apps.*; import gplx.xowa.apps.wms.*; import gplx.xowa.apps.wms.apis.*;
package gplx.xowa.addons.wikis.pages.syncs.core.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.syncs.*; import gplx.xowa.addons.wikis.pages.syncs.core.*;
import gplx.core.tests.*;
import gplx.langs.htmls.*; import gplx.xowa.htmls.*;
import gplx.xowa.files.*; import gplx.xowa.files.repos.*;
class Xowm_parse_mgr_fxt {
private final Wm_page_updater mgr = new Wm_page_updater();
public class Xosync_hdoc_parser__fxt {
private final Xosync_update_mgr mgr = new Xosync_update_mgr();
private final Bry_bfr tmp_bfr = Bry_bfr_.New();
private final Xoh_page hpg = new Xoh_page();
private Xowe_wiki wiki;
@ -31,11 +31,11 @@ class Xowm_parse_mgr_fxt {
mgr.Init_by_app(app);
mgr.Init_by_page(wiki, hpg);
}
public Xowm_parse_mgr_fxt Exec__parse(String raw) {
public Xosync_hdoc_parser__fxt Exec__parse(String raw) {
mgr.Parse(hpg, wiki, Bry_.Empty, Bry_.new_u8(raw));
return this;
}
public Xowm_parse_mgr_fxt Test__html(String expd) {
public Xosync_hdoc_parser__fxt Test__html(String expd) {
Gftest.Eq__ary__lines(expd, hpg.Db().Html().Html_bry(), "converted html");
return this;
}
@ -44,7 +44,7 @@ class Xowm_parse_mgr_fxt {
itm.Init_by_wm_parse(wiki.Domain_itm().Abrv_xo(), repo_is_commons, file_is_thumb, Bry_.new_u8(file_ttl), file_w, file_time, file_page);
return itm;
}
public Xowm_parse_mgr_fxt Test__fsdb(Xof_fsdb_itm expd) {
public Xosync_hdoc_parser__fxt Test__fsdb(Xof_fsdb_itm expd) {
Xof_fsdb_itm actl = (Xof_fsdb_itm)hpg.Hdump_mgr().Imgs().Get_at(0);
Gftest.Eq__str(To_str(tmp_bfr, expd), To_str(tmp_bfr, actl));
return this;

@ -15,11 +15,11 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.apps.wms.apis.parses; import gplx.*; import gplx.xowa.*; import gplx.xowa.apps.*; import gplx.xowa.apps.wms.*; import gplx.xowa.apps.wms.apis.*;
package gplx.xowa.addons.wikis.pages.syncs.core.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.syncs.*; import gplx.xowa.addons.wikis.pages.syncs.core.*;
import org.junit.*;
import gplx.langs.htmls.*;
public class Xowm_parse_mgr_tst {
@Before public void init() {fxt.Clear();} private final Xowm_parse_mgr_fxt fxt = new Xowm_parse_mgr_fxt();
public class Xosync_hdoc_parser__tst {
@Before public void init() {fxt.Clear();} private final Xosync_hdoc_parser__fxt fxt = new Xosync_hdoc_parser__fxt();
@Test public void Remove_edit() {
fxt.Exec__parse(Gfh_utl.Replace_apos_concat_lines
( "<h2><span class='mw-headline' id='Section_1'>Section_1</span>"

@ -15,9 +15,9 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.apps.wms.apis.parses; import gplx.*; import gplx.xowa.*; import gplx.xowa.apps.*; import gplx.xowa.apps.wms.*; import gplx.xowa.apps.wms.apis.*;
package gplx.xowa.addons.wikis.pages.syncs.core.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.*; import gplx.xowa.addons.wikis.pages.*; import gplx.xowa.addons.wikis.pages.syncs.*; import gplx.xowa.addons.wikis.pages.syncs.core.*;
import gplx.xowa.htmls.*; import gplx.xowa.htmls.core.wkrs.*; import gplx.xowa.htmls.core.hzips.*;
class Wm_hdoc_bldr implements Xoh_hdoc_wkr {
public class Xosync_hdoc_wtr implements Xoh_hdoc_wkr {
private Xoh_hzip_bfr bfr;
private byte[] src;
@ -28,17 +28,16 @@ class Wm_hdoc_bldr implements Xoh_hdoc_wkr {
this.bfr = bfr;
this.src = src;
}
public void On_txt (int rng_bgn, int rng_end) {bfr.Add_mid(src, rng_bgn, rng_end);}
public void Add_bfr(Bry_bfr v) {bfr.Add_bfr_and_clear(v);}
public void Add_str(String v) {bfr.Add_str_u8(v);}
public void Add_bry(byte[] v) {bfr.Add(v);}
public void On_txt (int rng_bgn, int rng_end) {bfr.Add_mid(src, rng_bgn, rng_end);}
public void Add_bfr (Bry_bfr v) {bfr.Add_bfr_and_clear(v);}
public void Add_str (String v) {bfr.Add_str_u8(v);}
public void Add_bry (byte[] v) {bfr.Add(v);}
// not used
public void On_escape (gplx.xowa.htmls.core.wkrs.escapes.Xoh_escape_data data) {}
public void On_xnde (gplx.xowa.htmls.core.wkrs.xndes.Xoh_xnde_parser parser) {}
public void On_lnki (gplx.xowa.htmls.core.wkrs.lnkis.Xoh_lnki_data parser) {}
public void On_thm (gplx.xowa.htmls.core.wkrs.thms.Xoh_thm_data parser) {}
public void On_gly (gplx.xowa.htmls.core.wkrs.glys.Xoh_gly_grp_data parser) {}
public boolean Process_parse(Xoh_data_itm data) {
return false;
}
public boolean Process_parse(Xoh_data_itm data) {return false;}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save