1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2026-03-02 03:49:30 +00:00
This commit is contained in:
gnosygnu
2014-08-03 23:31:22 -04:00
parent 7b6e65b088
commit fb8c06c560
191 changed files with 1869 additions and 722 deletions

View File

@@ -18,24 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.xowa; import gplx.*;
import gplx.xowa.langs.numbers.*;
public class Xow_fragment_mgr implements GfoInvkAble {
private static final byte[] Date_format_default = Bry_.new_ascii_("dmy");
private static final byte[] Num_format_digits = Bry_.new_ascii_("['', '']");
public byte[] Html_js_table() {return html_js_table;} private byte[] html_js_table;
public Xow_fragment_mgr(Xow_wiki wiki) {this.wiki = wiki;} private Xow_wiki wiki;
private Bry_fmtr html_js_table_fmtr = Bry_fmtr.new_(String_.Concat_lines_nl
( " var xowa_global_values = {"
, " 'collapsible-collapse' : '~{collapsible-collapse}',"
, " 'collapsible-expand' : '~{collapsible-expand}',"
, " 'sort-descending' : '~{sort-descending}',"
, " 'sort-ascending' : '~{sort-ascending}',"
, " 'wgContentLanguage' : '~{wgContentLanguage}',"
, " 'wgSeparatorTransformTable' : ~{wgSeparatorTransformTable},"
, " 'wgDigitTransformTable' : ~{wgDigitTransformTable},"
, " 'wgDefaultDateFormat' : '~{wgDefaultDateFormat}',"
, " 'wgMonthNames' : ~{wgMonthNames},"
, " 'wgMonthNamesShort' : ~{wgMonthNamesShort},"
, " };"
), "collapsible-collapse", "collapsible-expand", "sort-descending", "sort-ascending", "wgContentLanguage", "wgSeparatorTransformTable", "wgDigitTransformTable", "wgDefaultDateFormat", "wgMonthNames", "wgMonthNamesShort");
public byte[] Html_js_edit_toolbar() {return html_js_edit_toolbar;} private byte[] html_js_edit_toolbar;
private Bry_fmtr html_js_edit_toolbar_fmtr = Bry_fmtr.new_(String_.Concat_lines_nl
( " var xowa_edit_i18n = {"
@@ -54,33 +37,15 @@ public class Xow_fragment_mgr implements GfoInvkAble {
, " };"
), "bold_tip", "bold_sample", "italic_tip", "italic_sample", "link_tip", "link_sample", "headline_tip", "headline_sample", "ulist_tip", "ulist_sample", "olist_tip", "olist_sample");
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_html_js_table_fmt_)) html_js_table_fmtr.Fmt_(m.ReadBry("v"));
else if (ctx.Match(k, Invk_html_js_table)) return html_js_table;
else if (ctx.Match(k, Invk_html_js_edit_toolbar_fmt_)) html_js_edit_toolbar_fmtr.Fmt_(m.ReadBry("v"));
if (ctx.Match(k, Invk_html_js_edit_toolbar_fmt_)) html_js_edit_toolbar_fmtr.Fmt_(m.ReadBry("v"));
else if (ctx.Match(k, Invk_html_js_edit_toolbar)) return html_js_edit_toolbar;
else return GfoInvkAble_.Rv_unhandled;
return this;
}
public static final String Invk_html_js_table_fmt_ = "html_js_table_fmt_", Invk_html_js_table = "html_js_table", Invk_html_js_edit_toolbar_fmt_ = "html_js_edit_toolbar_fmt_", Invk_html_js_edit_toolbar = "html_js_edit_toolbar";
public static final String Invk_html_js_edit_toolbar_fmt_ = "html_js_edit_toolbar_fmt_", Invk_html_js_edit_toolbar = "html_js_edit_toolbar";
public void Evt_lang_changed(Xol_lang lang) {
Bry_bfr bfr = lang.App().Utl_bry_bfr_mkr().Get_b512();
Xow_msg_mgr msg_mgr = wiki.Msg_mgr();
byte[] months_long = Html_js_table_months(bfr, msg_mgr, Xol_msg_itm_.Id_dte_month_name_january, Xol_msg_itm_.Id_dte_month_name_december);
byte[] months_short = Html_js_table_months(bfr, msg_mgr, Xol_msg_itm_.Id_dte_month_abrv_jan, Xol_msg_itm_.Id_dte_month_abrv_dec);
byte[] num_format_separators = Html_js_table_num_format_separators(bfr, lang.Num_mgr().Separators_mgr());
html_js_table = html_js_table_fmtr.Bld_bry_many(bfr
, msg_mgr.Val_by_id(Xol_msg_itm_.Id_js_tables_collapsible_collapse)
, msg_mgr.Val_by_id(Xol_msg_itm_.Id_js_tables_collapsible_expand)
, msg_mgr.Val_by_id(Xol_msg_itm_.Id_js_tables_sort_descending)
, msg_mgr.Val_by_id(Xol_msg_itm_.Id_js_tables_sort_ascending)
, lang.Key_bry()
, num_format_separators
, Num_format_digits
, Date_format_default
, months_long
, months_short
);
msg_mgr = wiki.App().User().Msg_mgr();
Xow_msg_mgr msg_mgr = wiki.App().User().Msg_mgr();
html_js_edit_toolbar = html_js_edit_toolbar_fmtr.Bld_bry_many(bfr
, msg_mgr.Val_by_id(Xol_msg_itm_.Id_edit_toolbar_bold_tip)
, msg_mgr.Val_by_id(Xol_msg_itm_.Id_edit_toolbar_bold_sample)
@@ -97,23 +62,4 @@ public class Xow_fragment_mgr implements GfoInvkAble {
);
bfr.Mkr_rls();
}
byte[] Html_js_table_months(Bry_bfr bfr, Xow_msg_mgr msg_mgr, int january_id, int december_id) {
// ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
bfr.Add_byte(Byte_ascii.Brack_bgn).Add_byte(Byte_ascii.Apos).Add_byte(Byte_ascii.Apos);
for (int i = january_id; i <= december_id; i++) {
bfr.Add_byte(Byte_ascii.Comma).Add_byte(Byte_ascii.Space).Add_byte(Byte_ascii.Apos);
bfr.Add(msg_mgr.Val_by_id(i));
bfr.Add_byte(Byte_ascii.Apos);
}
bfr.Add_byte(Byte_ascii.Brack_end);
return bfr.XtoAryAndClear();
}
private byte[] Html_js_table_num_format_separators(Bry_bfr bfr, Xol_transform_mgr separator_mgr) {
byte[] dec_spr = separator_mgr.Get_val_or_self(Xol_num_mgr.Separators_key__dec);
bfr.Add_byte(Byte_ascii.Brack_bgn) .Add_byte(Byte_ascii.Apos).Add(dec_spr).Add_byte(Byte_ascii.Tab).Add_byte(Byte_ascii.Dot).Add_byte(Byte_ascii.Apos);
byte[] grp_spr = separator_mgr.Get_val_or_self(Xol_num_mgr.Separators_key__grp);
bfr.Add_byte(Byte_ascii.Comma).Add_byte(Byte_ascii.Space) .Add_byte(Byte_ascii.Apos).Add(grp_spr).Add_byte(Byte_ascii.Tab).Add_byte(Byte_ascii.Comma).Add_byte(Byte_ascii.Apos);
bfr.Add_byte(Byte_ascii.Brack_end);
return bfr.XtoAryAndClear();
}
}

View File

@@ -21,42 +21,6 @@ import gplx.xowa.langs.numbers.*;
public class Xow_fragment_mgr_tst {
Xow_fragment_mgr_fxt fxt = new Xow_fragment_mgr_fxt();
@Before public void init() {fxt.Clear();}
@Test public void Html_js_table_fmt() {
fxt.Test_fragment(Xow_fragment_mgr.Invk_html_js_table, String_.Concat_lines_nl
( " var xowa_global_values = {"
, " 'collapsible-collapse' : 'Collapse',"
, " 'collapsible-expand' : 'Expand',"
, " 'sort-descending' : 'Sort descending',"
, " 'sort-ascending' : 'Sort ascending',"
, " 'wgContentLanguage' : 'en',"
, " 'wgSeparatorTransformTable' : ['.\t.', ',\t,'],"
, " 'wgDigitTransformTable' : ['', ''],"
, " 'wgDefaultDateFormat' : 'dmy',"
, " 'wgMonthNames' : ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],"
, " 'wgMonthNamesShort' : ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],"
, " };"
));
}
@Test public void Html_js_table_fmt_la() { // PURPOSE: la.gfs only specifies "," not "."; make sure both "." and "," show up, or else null ref error during import; DATE:2014-05-13
Xol_lang la_lang = fxt.Make_lang("la");
Xol_transform_mgr separators_mgr = la_lang.Num_mgr().Separators_mgr();
separators_mgr.Clear();
separators_mgr.Set(Xol_num_mgr.Separators_key__grp, Bry_.new_ascii_(" "));
fxt.Test_fragment(la_lang, Xow_fragment_mgr.Invk_html_js_table, String_.Concat_lines_nl
( " var xowa_global_values = {"
, " 'collapsible-collapse' : 'Collapse',"
, " 'collapsible-expand' : 'Expand',"
, " 'sort-descending' : 'Sort descending',"
, " 'sort-ascending' : 'Sort ascending',"
, " 'wgContentLanguage' : 'la',"
, " 'wgSeparatorTransformTable' : ['.\t.', ' \t,'],"
, " 'wgDigitTransformTable' : ['', ''],"
, " 'wgDefaultDateFormat' : 'dmy',"
, " 'wgMonthNames' : ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],"
, " 'wgMonthNamesShort' : ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],"
, " };"
));
}
@Test public void Html_js_edit_toolbar_fmt() {
fxt.Test_fragment(Xow_fragment_mgr.Invk_html_js_edit_toolbar, String_.Concat_lines_nl
( " var xowa_edit_i18n = {"

View File

@@ -16,6 +16,7 @@ You should have received 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.xwikis.*;
public class Xow_lang_itm {
public Xow_lang_itm(Xow_lang_grp html_grp, Xow_xwiki_itm xwiki, Xoac_lang_itm lang) {
this.html_grp = html_grp; this.xwiki = xwiki; this.lang = lang;

View File

@@ -16,17 +16,20 @@ You should have received 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.xwikis.*; import gplx.xowa.apis.xowa.html.*;
public class Xow_lang_mgr {
Xow_lang_mgr() {
int len = Xol_lang_itm_.Id__max;
itms = new Xow_lang_itm[len];
}
public Bry_fmtr Html_div() {return html_div;} Bry_fmtr html_div = Bry_fmtr.new_(
String_.Concat_lines_nl_skip_last
( "<div id=\"xowa-lang\">"
, " <h5>~{langs_hdr}~{wikidata_link}</h5>~{grps}"
, "</div>"
), "grps", "langs_hdr", "wikidata_link");
public Bry_fmtr Html_div() {return html_div;} Bry_fmtr html_div = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
( "<div id=\"xowa-lang\">"
, " <h5>~{langs_hdr}~{wikidata_link}<a href='javascript:xowa_toggle_visible(\"wikidata-langs\");'><img id='wikidata-langs-toggle-icon' src='~{icon_src}' title='~{icon_title}' /></a></h5>"
, " <div id='wikidata-langs-toggle-elem' style='~{elem_display}'>~{grps}"
, " </div>"
, "</div>"
), "langs_hdr", "wikidata_link", "icon_src", "icon_title", "elem_display", "grps");
public Bry_fmtr Html_wikidata_link() {return html_wikidata_link;} Bry_fmtr html_wikidata_link = Bry_fmtr.new_(" (<a href=\"/site/www.wikidata.org/wiki/~{qid}\">wikidata</a>)", "qid");
public void Clear() {hash.Clear();}
public void Itms_reg(Xow_xwiki_itm xwiki, Xoac_lang_itm lang) {
@@ -103,8 +106,10 @@ class Xow_lang_html implements Bry_fmtr_arg {
case 0: {
stage = 1;
Bry_bfr tmp_bfr = wiki.Utl_bry_bfr_mkr().Get_b128().Mkr_rls();
byte[] msg_lang = wiki.Msg_mgr().Val_by_id(Xol_msg_itm_.Id_page_lang_header);
byte[] wikidata_link = Bry_.Len_eq_0(qid) ? Bry_.Empty : lang_mgr.Html_wikidata_link().Bld_bry_many(tmp_bfr, qid);
lang_mgr.Html_div().Bld_bfr_many(bfr, this, wiki.Msg_mgr().Val_by_id(Xol_msg_itm_.Id_page_lang_header), wikidata_link);
Xoapi_toggle_itm visible_data = wiki.App().Api_root().Html().Page().Toggle_mgr().Itm_wikidata_langs().Init(wiki);
lang_mgr.Html_div().Bld_bfr_many(bfr, msg_lang, wikidata_link, visible_data.Icon_src(), visible_data.Icon_title(), visible_data.Elem_display(), this);
stage = 0;
break;
}

View File

@@ -22,64 +22,72 @@ public class Xow_lang_mgr_tst {
@Before public void init() {fxt.Clear();}
@Test public void Basic() {
fxt.tst("[[simple:Earth]] [[fr:Terre]] [[es:Tierra]] [[de:Erde]] [[it:Terre]]", String_.Concat_lines_nl_skip_last
( "<div id=\"xowa-lang\">"
, " <h5>In other languages</h5>"
, " <h4>grp1</h4>"
, " <table style='width: 100%;'>"
, " <tr>"
, " <td style='width: 10%; padding-bottom: 5px;'>Simple</td><td style='width: 20%; padding-bottom: 5px;'><a hreflang=\"simple\" title=\"Earth\" href=\"/site/simple.wikipedia.org/wiki/Earth\">Earth</a></td><td style='width: 3%; padding-bottom: 5px;'></td>"
, " <td style='width: 10%; padding-bottom: 5px;'>Spanish</td><td style='width: 20%; padding-bottom: 5px;'><a hreflang=\"es\" title=\"Tierra\" href=\"/site/es.wikipedia.org/wiki/Tierra\">Tierra</a></td><td style='width: 3%; padding-bottom: 5px;'></td>"
, " <td style='width: 10%; padding-bottom: 5px;'>Italian</td><td style='width: 20%; padding-bottom: 5px;'><a hreflang=\"it\" title=\"Terre\" href=\"/site/it.wikipedia.org/wiki/Terre\">Terre</a></td><td style='width: 3%; padding-bottom: 5px;'></td>"
, " </tr>"
, " </table>"
, " <h4>grp2</h4>"
, " <table style='width: 100%;'>"
, " <tr>"
, " <td style='width: 10%; padding-bottom: 5px;'>French</td><td style='width: 20%; padding-bottom: 5px;'><a hreflang=\"fr\" title=\"Terre\" href=\"/site/fr.wikipedia.org/wiki/Terre\">Terre</a></td><td style='width: 3%; padding-bottom: 5px;'></td>"
, " <td style='width: 10%; padding-bottom: 5px;'>German</td><td style='width: 20%; padding-bottom: 5px;'><a hreflang=\"de\" title=\"Erde\" href=\"/site/de.wikipedia.org/wiki/Erde\">Erde</a></td><td style='width: 3%; padding-bottom: 5px;'></td>"
, " </tr>"
, " </table>"
, "</div>"
));
( "<div id=\"xowa-lang\">"
, " <h5>In other languages<a href='javascript:xowa_toggle_visible(\"wikidata-langs\");'><img id='wikidata-langs-toggle-icon' src='file:///mem/xowa/user/test_user/app/img/window/portal/twisty_right.png' title='' /></a></h5>"
, " <div id='wikidata-langs-toggle-elem' style='display:none;'>"
, " <h4>grp1</h4>"
, " <table style='width: 100%;'>"
, " <tr>"
, " <td style='width: 10%; padding-bottom: 5px;'>Simple</td><td style='width: 20%; padding-bottom: 5px;'><a hreflang=\"simple\" title=\"Earth\" href=\"/site/simple.wikipedia.org/wiki/Earth\">Earth</a></td><td style='width: 3%; padding-bottom: 5px;'></td>"
, " <td style='width: 10%; padding-bottom: 5px;'>Spanish</td><td style='width: 20%; padding-bottom: 5px;'><a hreflang=\"es\" title=\"Tierra\" href=\"/site/es.wikipedia.org/wiki/Tierra\">Tierra</a></td><td style='width: 3%; padding-bottom: 5px;'></td>"
, " <td style='width: 10%; padding-bottom: 5px;'>Italian</td><td style='width: 20%; padding-bottom: 5px;'><a hreflang=\"it\" title=\"Terre\" href=\"/site/it.wikipedia.org/wiki/Terre\">Terre</a></td><td style='width: 3%; padding-bottom: 5px;'></td>"
, " </tr>"
, " </table>"
, " <h4>grp2</h4>"
, " <table style='width: 100%;'>"
, " <tr>"
, " <td style='width: 10%; padding-bottom: 5px;'>French</td><td style='width: 20%; padding-bottom: 5px;'><a hreflang=\"fr\" title=\"Terre\" href=\"/site/fr.wikipedia.org/wiki/Terre\">Terre</a></td><td style='width: 3%; padding-bottom: 5px;'></td>"
, " <td style='width: 10%; padding-bottom: 5px;'>German</td><td style='width: 20%; padding-bottom: 5px;'><a hreflang=\"de\" title=\"Erde\" href=\"/site/de.wikipedia.org/wiki/Erde\">Erde</a></td><td style='width: 3%; padding-bottom: 5px;'></td>"
, " </tr>"
, " </table>"
, " </div>"
, "</div>"
));
}
@Test public void Empty() {
fxt.tst("[[simple:]]", String_.Concat_lines_nl_skip_last
( "<div id=\"xowa-lang\">"
, " <h5>In other languages</h5>"
, " <h4>grp1</h4>"
, " <table style='width: 100%;'>"
, " <tr>"
, " <td style='width: 10%; padding-bottom: 5px;'>Simple</td><td style='width: 20%; padding-bottom: 5px;'><a hreflang=\"simple\" title=\"Test page\" href=\"/site/simple.wikipedia.org/wiki/\">Test page</a></td><td style='width: 3%; padding-bottom: 5px;'></td>"
, " </tr>"
, " </table>"
, "</div>"
));
( "<div id=\"xowa-lang\">"
, " <h5>In other languages<a href='javascript:xowa_toggle_visible(\"wikidata-langs\");'><img id='wikidata-langs-toggle-icon' src='file:///mem/xowa/user/test_user/app/img/window/portal/twisty_right.png' title='' /></a></h5>"
, " <div id='wikidata-langs-toggle-elem' style='display:none;'>"
, " <h4>grp1</h4>"
, " <table style='width: 100%;'>"
, " <tr>"
, " <td style='width: 10%; padding-bottom: 5px;'>Simple</td><td style='width: 20%; padding-bottom: 5px;'><a hreflang=\"simple\" title=\"Test page\" href=\"/site/simple.wikipedia.org/wiki/\">Test page</a></td><td style='width: 3%; padding-bottom: 5px;'></td>"
, " </tr>"
, " </table>"
, " </div>"
, "</div>"
));
}
@Test public void Unregistered() {
// fxt.Wiki().Xwiki_mgr().Add_full(Bry_.new_utf8_("zh"), Bry_.new_utf8_("zh.wikipedia.org"), Bry_.new_utf8_("http://zh.wikipedia.org/~{0}"));
fxt.tst("[[zh:Earth]]", String_.Concat_lines_nl_skip_last
( "<div id=\"xowa-lang\">"
, " <h5>In other languages</h5>"
, " <h4>grp1</h4>"
, " <table style='width: 100%;'>"
, " <tr>"
, " <td style='width: 10%; padding-bottom: 5px;'>Chinese</td><td style='width: 20%; padding-bottom: 5px;'><a hreflang=\"zh\" title=\"Earth\" href=\"http://zh.wikipedia.org/wiki/Earth\">Earth</a></td><td style='width: 3%; padding-bottom: 5px;'></td>"
, " </tr>"
, " </table>"
, "</div>"
));
( "<div id=\"xowa-lang\">"
, " <h5>In other languages<a href='javascript:xowa_toggle_visible(\"wikidata-langs\");'><img id='wikidata-langs-toggle-icon' src='file:///mem/xowa/user/test_user/app/img/window/portal/twisty_right.png' title='' /></a></h5>"
, " <div id='wikidata-langs-toggle-elem' style='display:none;'>"
, " <h4>grp1</h4>"
, " <table style='width: 100%;'>"
, " <tr>"
, " <td style='width: 10%; padding-bottom: 5px;'>Chinese</td><td style='width: 20%; padding-bottom: 5px;'><a hreflang=\"zh\" title=\"Earth\" href=\"http://zh.wikipedia.org/wiki/Earth\">Earth</a></td><td style='width: 3%; padding-bottom: 5px;'></td>"
, " </tr>"
, " </table>"
, " </div>"
, "</div>"
));
}
@Test public void Anchor() {// PURPOSE: A#b was not showing anchor "#b"; DATE:2013-10-23
fxt.tst("[[simple:A#b]]", String_.Concat_lines_nl_skip_last
( "<div id=\"xowa-lang\">"
, " <h5>In other languages</h5>"
, " <h4>grp1</h4>"
, " <table style='width: 100%;'>"
, " <tr>"
, " <td style='width: 10%; padding-bottom: 5px;'>Simple</td><td style='width: 20%; padding-bottom: 5px;'><a hreflang=\"simple\" title=\"A#b\" href=\"/site/simple.wikipedia.org/wiki/A#b\">A#b</a></td><td style='width: 3%; padding-bottom: 5px;'></td>"
, " </tr>"
, " </table>"
, "</div>"
));
( "<div id=\"xowa-lang\">"
, " <h5>In other languages<a href='javascript:xowa_toggle_visible(\"wikidata-langs\");'><img id='wikidata-langs-toggle-icon' src='file:///mem/xowa/user/test_user/app/img/window/portal/twisty_right.png' title='' /></a></h5>"
, " <div id='wikidata-langs-toggle-elem' style='display:none;'>"
, " <h4>grp1</h4>"
, " <table style='width: 100%;'>"
, " <tr>"
, " <td style='width: 10%; padding-bottom: 5px;'>Simple</td><td style='width: 20%; padding-bottom: 5px;'><a hreflang=\"simple\" title=\"A#b\" href=\"/site/simple.wikipedia.org/wiki/A#b\">A#b</a></td><td style='width: 3%; padding-bottom: 5px;'></td>"
, " </tr>"
, " </table>"
, " </div>"
, "</div>"
));
}
}

View File

@@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.xowa; import gplx.*;
import gplx.xowa.apps.*;
import gplx.xowa.wikis.*; import gplx.xowa.users.*; import gplx.xowa.html.*; import gplx.xowa.users.history.*; import gplx.xowa.specials.*; import gplx.xowa.xtns.*; import gplx.xowa.dbs.*; import gplx.xowa.files.*;
import gplx.xowa.langs.vnts.*; import gplx.xowa.gui.views.*;
import gplx.xowa.langs.vnts.*; import gplx.xowa.gui.views.*; import gplx.xowa.wikis.xwikis.*;
import gplx.xowa.setup.maints.*; import gplx.xowa.wikis.caches.*;
import gplx.xowa.bldrs.imports.*; import gplx.xowa.xtns.pfuncs.*;
public class Xow_wiki implements GfoInvkAble {

View File

@@ -1,30 +0,0 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa; import gplx.*;
public class Xow_xwiki_itm implements gplx.CompareAble {
public Xow_xwiki_itm(byte[] key, byte[] fmt, byte wiki_tid, int lang_id, byte[] domain) {this.key = key; this.fmt = fmt; this.wiki_tid = wiki_tid; this.lang_id = lang_id; this.domain = domain; this.key_str = String_.new_utf8_(key);}
public byte[] Key() {return key;} private byte[] key;
public String Key_str() {return key_str;} private String key_str;
public byte[] Fmt() {return fmt;} private byte[] fmt;
public byte[] Domain() {return domain;} private byte[] domain;
public byte Wiki_tid() {return wiki_tid;} private byte wiki_tid;
public int Lang_id() {return lang_id;} private int lang_id;
public boolean Type_is_lang(int cur_lang_id) {return lang_id != Xol_lang_itm_.Id__unknown && cur_lang_id != lang_id && Bry_.Len_gt_0(fmt);}
public boolean Offline() {return offline;} public Xow_xwiki_itm Offline_(boolean v) {offline = v; return this;} private boolean offline;
public int compareTo(Object obj) {Xow_xwiki_itm comp = (Xow_xwiki_itm)obj; return Bry_.Compare(key, comp.key);}
}

View File

@@ -1,185 +0,0 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa; import gplx.*;
import gplx.xowa.wikis.*;
public class Xow_xwiki_mgr implements GfoInvkAble {
public Xow_xwiki_mgr(Xow_wiki wiki) {this.wiki = wiki;} private Xow_wiki wiki;
public Xow_lang_mgr Lang_mgr() {return lang_mgr;} private Xow_lang_mgr lang_mgr = Xow_lang_mgr.dflt_();
public int Len() {return list.Count();} private OrderedHash list = OrderedHash_.new_bry_(); private Hash_adp_bry hash = Hash_adp_bry.ci_ascii_(); // ASCII:lang_code
public void Clear() {hash.Clear(); list.Clear();}
public Xow_xwiki_itm Get_at(int i) {return (Xow_xwiki_itm)list.FetchAt(i);}
public Xow_xwiki_itm Get_by_key(byte[] key) {return (Xow_xwiki_itm)hash.Get_by_bry(key);}
public Xow_xwiki_itm Get_by_mid(byte[] src, int bgn, int end) {return (Xow_xwiki_itm)hash.Get_by_mid(src, bgn, end);}
public void Add_full(String alias, String domain) {Add_full(Bry_.new_ascii_(alias), Bry_.new_ascii_(domain), null);}
public void Add_full(byte[] alias, byte[] domain) {Add_full(alias, domain, null);}
public void Add_full(byte[] alias, byte[] domain, byte[] fmt) {
byte wiki_tid = Byte_.Zero;
int lang_tid = -1;
Xow_wiki_domain wiki_type = Xow_wiki_domain_.parse_by_domain(domain);
wiki_tid = wiki_type.Tid();
if (Bry_.Len_gt_0(wiki_type.Lang())) { // domain has lang (EX: "en.")
Xol_lang_itm lang_itm = Xol_lang_itm_.Get_by_key(wiki_type.Lang());
if (lang_itm == null) return; // unknown lang: do not add to wiki collection; EX: en1.wikipedia.org
lang_tid = lang_itm.Id();
}
Xow_xwiki_itm itm = new Xow_xwiki_itm(alias, fmt, wiki_tid, lang_tid, domain);
Add_itm(itm, null);
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_count)) return list.Count();
else if (ctx.Match(k, Invk_add_bulk)) Add_bulk(m.ReadBry("v"));
else if (ctx.Match(k, Invk_add_bulk_langs)) Add_bulk_langs(m);
else if (ctx.Match(k, Invk_add_bulk_peers)) Add_bulk_peers(m.ReadBry("v"));
else if (ctx.Match(k, Invk_itms_print)) return Exec_itms_print(m.ReadBry("v"));
else if (ctx.Match(k, Invk_clear)) this.Clear();
else return GfoInvkAble_.Rv_unhandled;
return this;
} public static final String Invk_add_bulk = "add_bulk", Invk_add_bulk_langs = "add_bulk_langs", Invk_add_bulk_peers = "add_bulk_peers", Invk_itms_print = "itms_print", Invk_count = "count", Invk_clear = "clear";
public void Sort_by_key() {
list.Sort();
}
public void Add_bulk(byte[] raw) {
byte[][] rows = Bry_.Split(raw, Byte_ascii.NewLine);
int rows_len = rows.length;
Hash_adp_bry lang_regy = Xol_lang_itm_.Regy();
for (int i = 0; i < rows_len; i++) {
byte[] row = rows[i]; if (Bry_.Len_eq_0(row)) continue; // ignore blank rows
Xow_xwiki_itm itm = Add_bulk_row(lang_regy, row);
Add_itm(itm, null);
}
}
public Xow_xwiki_itm Add_bulk_row(Hash_adp_bry lang_regy, byte[] row) {
byte[][] flds = Bry_.Split(row, Byte_ascii.Pipe); int flds_len = flds.length;
byte[] alias = Bry_.Empty, wiki_type_bry = Bry_.Empty;
for (int j = 0; j < flds_len; j++) {
byte[] fld = flds[j];
switch (j) {
case 0: alias = fld; break;
case 1: wiki_type_bry = fld; break;
case 2: break; // reserved for 0,1 (0=custom; 1=wmf)
default: throw Err_mgr._.unhandled_(j);
}
}
Xow_wiki_domain wiki_type = Xow_wiki_domain_.parse_by_domain(wiki_type_bry);
int lang_tid = Xol_lang_itm_.Id__unknown;
if (Bry_.Len_gt_0(wiki_type.Lang())) {
Xol_lang_itm lang_itm = Xol_lang_itm_.Get_by_key(wiki_type.Lang());
if (lang_itm != null // lang exists
&& Bry_.Eq(alias, lang_itm.Key())) // alias == lang.key; only assign langs to aliases that have lang key; EX: w|en.wikipedia.org; "w" alias should not be registered for "en"; DATE:2013-07-25
lang_tid = lang_itm.Id();
}
return new Xow_xwiki_itm(alias, Bry_.Add(Xoh_href_parser.Href_http_bry, wiki_type_bry, Xoh_href_parser.Href_wiki_bry, Arg_0), wiki_type.Tid(), lang_tid, wiki_type_bry);
} static final byte[] Arg_0 = Bry_.new_ascii_("~{0}");
String Exec_itms_print(byte[] raw) {
Bry_fmtr fmtr = Bry_fmtr.new_bry_(raw, "wiki_key");//, "wiki_type_url", "wiki_lang", "wiki_name", "wiki_logo_url");
Bry_bfr tmp_bfr = wiki.Utl_bry_bfr_mkr().Get_k004();
Hash_adp_bry seen = Hash_adp_bry.ci_ascii_(); // ASCII:url_domain; EX:en.wikipedia.org
int wikis_len = list.Count();
for (int i = 0; i < wikis_len; i++) {
Xow_xwiki_itm itm = (Xow_xwiki_itm)list.FetchAt(i);
byte[] key = itm.Key();
if (Bry_.Eq(key, Xow_wiki_domain_.Key_home_bry)) continue; // skip home
byte[] domain = itm.Domain();
if (seen.Has(domain)) continue;
seen.AddKeyVal(domain);
fmtr.Bld_bfr_many(tmp_bfr, key);
}
return tmp_bfr.Mkr_rls().XtoStrAndClear();
}
public void Add_bulk_peers(byte[] raw) {
byte[][] keys = Bry_.Split(raw, Byte_ascii.Tilde);
int len = keys.length;
OrderedHash peers = OrderedHash_.new_();
Cfg_nde_root peer_root = wiki.App().Wiki_mgr().Groups();
for (int i = 0; i < len; i++) {
byte[] key = keys[i];
Cfg_nde_obj peer_grp = peer_root.Grps_get(key);
if (peer_grp == null)
throw Err_mgr._.fmt_(GRP_KEY, "invalid_peer", "unknown peer group: ~{0}", String_.new_utf8_(key));
else
Cfg_nde_obj_.Fill_recurse(peers, peer_grp);
}
len = peers.Count();
byte[] lang_key_bry = wiki.Lang().Key_bry();
if (lang_key_bry == Xol_lang_itm_.Key__unknown) lang_key_bry = Xol_lang_.Key_en; // default non-lang wikis to english
String lang_key_str = String_.new_utf8_(lang_key_bry);
int lang_id = Xol_lang_itm_.Get_by_key(lang_key_bry).Id();
byte wiki_tid = wiki.Domain_tid();
for (int i = 0; i < len; i++) {
Xoac_wiki_itm wiki_itm = (Xoac_wiki_itm)peers.FetchAt(i);
byte[] wiki_name_bry = wiki_itm.Key_bry();
String wiki_name = String_.new_utf8_(wiki_name_bry);
String domain_str = null;
byte xwiki_tid_val = Xow_wiki_domain_.Tid_by_key(wiki_name_bry);
switch (xwiki_tid_val) {
case Xow_wiki_domain_.Tid_commons:
case Xow_wiki_domain_.Tid_species:
case Xow_wiki_domain_.Tid_meta:
case Xow_wiki_domain_.Tid_incubator: domain_str = String_.Format("{0}.wikimedia.org", wiki_name); break; // EX: commons.wikimedia.org
case Xow_wiki_domain_.Tid_wikidata: domain_str = String_.Format("www.wikidata.org", wiki_name); break; // EX: www.wikidata.org
case Xow_wiki_domain_.Tid_mediawiki: domain_str = String_.Format("www.mediawiki.org", wiki_name); break;
case Xow_wiki_domain_.Tid_wikimediafoundation: domain_str = String_.Format("wikimediafoundation.org", wiki_name); break;
default: domain_str = String_.Format("{0}.{1}.org", lang_key_str, wiki_name); break; // EX: en.wiktionary.org
}
byte[] domain_bry = Bry_.new_utf8_(domain_str);
Xow_wiki lang_wiki = wiki.App().Wiki_mgr().Get_by_key_or_null(domain_bry);
boolean offline_exists = lang_wiki != null;
String fmt = String_.Format("http://" + domain_str + "/wiki/~{0}");
int aliases_len = wiki_itm.Aliases().length;
for (int j = 0; j < aliases_len; j++) {
byte[] alias = wiki_itm.Aliases()[j];
if (wiki.Ns_mgr().Names_get_or_null(alias, 0, alias.length) != null) continue; // NOTE: do not add xwiki if alias matches namespace; EX: en.wiktionary.org has ns of "Wiktionary"; do not add alias of "wiktionary"; note that wikipedia does have an alias to wiktionary
Xow_xwiki_itm xwiki = new Xow_xwiki_itm(alias, Bry_.new_utf8_(fmt), wiki_tid, lang_id, domain_bry).Offline_(offline_exists);
Add_itm(xwiki, null);
}
}
}
public void Add_bulk_langs(GfoMsg m) {
byte[] grp_key = m.ReadBry("grp_key");
byte[] wiki_type_name = m.ReadBryOr("wiki_type_name", null);
byte wiki_tid = wiki_type_name == null ? wiki.Domain_tid() : Xow_wiki_domain_.Tid_by_key(wiki_type_name);
Add_bulk_langs(grp_key, wiki_tid);
}
public void Add_bulk_langs(byte[] grp_key) {Add_bulk_langs(grp_key, wiki.Domain_tid());}
private void Add_bulk_langs(byte[] grp_key, byte wiki_tid) {
OrderedHash langs = wiki.App().Lang_mgr().Xto_hash(grp_key);
int len = langs.Count();
byte[] wiki_tid_name = Xow_wiki_domain_.Key_by_tid(wiki_tid);
String wiki_tid_name_str = String_.new_utf8_(wiki_tid_name);
for (int i = 0; i < len; i++) {
Xoac_lang_itm lang = (Xoac_lang_itm)langs.FetchAt(i);
String domain_str = String_.Format("{0}.{1}.org", String_.new_utf8_(lang.Key_bry()), wiki_tid_name_str); // EX: fr.wikipedia.org
byte[] domain_bry = Bry_.new_utf8_(domain_str);
Xow_wiki lang_wiki = wiki.App().Wiki_mgr().Get_by_key_or_null(domain_bry);
boolean offline_exists = lang_wiki != null;
String fmt = String_.Format("http://" + domain_str + "/wiki/~{0}");
int lang_id = Xol_lang_itm_.Get_by_key(lang.Key_bry()).Id();
Xow_xwiki_itm xwiki = new Xow_xwiki_itm(lang.Key_bry(), Bry_.new_utf8_(fmt), wiki_tid, lang_id, domain_bry).Offline_(offline_exists);
Add_itm(xwiki, lang);
}
lang_mgr.Grps_sort();
} private static final String GRP_KEY = "xowa.wiki.xwikis";
private void Add_itm(Xow_xwiki_itm xwiki, Xoac_lang_itm lang) {
if ( !hash.Has(xwiki.Key()) // only register xwiki / lang pair once
&& lang != null) // null lang should not be registered
lang_mgr.Itms_reg(xwiki, lang);
hash.AddReplace(xwiki.Key(), xwiki);
list.AddReplace(xwiki.Key(), xwiki);
}
}

View File

@@ -1,124 +0,0 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa; import gplx.*;
import org.junit.*; import gplx.xowa.wikis.*; import gplx.xowa.langs.*;
public class Xow_xwiki_mgr_tst {
Xow_xwiki_mgr_fxt fxt = new Xow_xwiki_mgr_fxt();
@Before public void init() {fxt.Clear();}
@Test public void Add_bulk_wiki_en() {fxt.Tst_add_bulk("w|en.wikipedia.org" , Xol_lang_itm_.Id__unknown , Xow_wiki_domain_.Tid_wikipedia , "w" , "http://en.wikipedia.org/wiki/~{0}", "en.wikipedia.org");}
@Test public void Add_bulk_wiki_fr() {fxt.Tst_add_bulk("fr|fr.wikipedia.org" , Xol_lang_itm_.Id_fr , Xow_wiki_domain_.Tid_wikipedia , "fr" , "http://fr.wikipedia.org/wiki/~{0}", "fr.wikipedia.org");}
@Test public void Add_bulk_wikt_en() {fxt.Tst_add_bulk("wikt|en.wiktionary.org" , Xol_lang_itm_.Id__unknown , Xow_wiki_domain_.Tid_wiktionary , "wikt" , "http://en.wiktionary.org/wiki/~{0}", "en.wiktionary.org");}
@Test public void Add_bulk_commons() {fxt.Tst_add_bulk("commons|commons.wikimedia.org" , Xol_lang_itm_.Id__unknown , Xow_wiki_domain_.Tid_commons , "commons" , "http://commons.wikimedia.org/wiki/~{0}", "commons.wikimedia.org");}
@Test public void Add_bulk_commons_cap() {fxt.Tst_add_bulk("Commons|commons.wikimedia.org" , Xol_lang_itm_.Id__unknown , Xow_wiki_domain_.Tid_commons , "Commons" , "http://commons.wikimedia.org/wiki/~{0}", "commons.wikimedia.org");}
@Test public void Add_bulk_langs_wiki() {fxt.Langs_ini().Tst_add_bulk_langs("wiki", fxt.xwiki_("en", "en.wikipedia.org", "http://en.wikipedia.org/wiki/~{0}"), fxt.xwiki_("de", "de.wikipedia.org", "http://de.wikipedia.org/wiki/~{0}"), fxt.xwiki_("fr", "fr.wikipedia.org", "http://fr.wikipedia.org/wiki/~{0}"), fxt.xwiki_("ja", "ja.wikipedia.org", "http://ja.wikipedia.org/wiki/~{0}"));}
@Test public void Add_bulk_langs_grps() {fxt.Langs_ini().Tst_add_bulk_langs("europe_west~asia_east", fxt.xwiki_("de", "de.wikipedia.org", "http://de.wikipedia.org/wiki/~{0}"), fxt.xwiki_("fr", "fr.wikipedia.org", "http://fr.wikipedia.org/wiki/~{0}"), fxt.xwiki_("ja", "ja.wikipedia.org", "http://ja.wikipedia.org/wiki/~{0}"));}
@Test public void Add_bulk_langs_grp_itm() {fxt.Langs_ini().Tst_add_bulk_langs("europe_west~ja", fxt.xwiki_("de", "de.wikipedia.org", "http://de.wikipedia.org/wiki/~{0}"), fxt.xwiki_("fr", "fr.wikipedia.org", "http://fr.wikipedia.org/wiki/~{0}"), fxt.xwiki_("ja", "ja.wikipedia.org", "http://ja.wikipedia.org/wiki/~{0}"));}
@Test public void Add_bulk_langs_grp_commons() {
fxt.Langs_ini();
GfoInvkAble_.InvkCmd_msg(fxt.Wiki().Xwiki_mgr(), Xow_xwiki_mgr.Invk_add_bulk_langs, GfoMsg_.new_parse_(Xow_xwiki_mgr.Invk_add_bulk_langs).Add("grp_key", "europe_west").Add("wiki_type_name", "wikipedia"));
fxt.Tst_itms(fxt.xwiki_("de", "de.wikipedia.org", "http://de.wikipedia.org/wiki/~{0}"), fxt.xwiki_("fr", "fr.wikipedia.org", "http://fr.wikipedia.org/wiki/~{0}"));
}
@Test public void Add_bulk_peers() {fxt.Peers_ini().Tst_add_bulk_peers("peer", fxt.xwiki_null_("commons"), fxt.xwiki_null_("m"), fxt.xwiki_("wikt", "en.wiktionary.org", "http://en.wiktionary.org/wiki/~{0}"), fxt.xwiki_("wiktionary", "en.wiktionary.org", "http://en.wiktionary.org/wiki/~{0}"), fxt.xwiki_("s", "en.wikisource.org", "http://en.wikisource.org/wiki/~{0}"));}
@Test public void Add_bulk_peers_skip_self() {fxt.Peers_ini().Tst_add_bulk_peers("peer", fxt.xwiki_null_("wikipedia"), fxt.xwiki_("w", "en.wikipedia.org", "http://en.wikipedia.org/wiki/~{0}"));} // PURPOSE: skip "wikipedia" as alias since "Wikipedia" is namespace; needed for titles of "Wikipedia:Main page" (which would otherwise try to go to page "Main Page" in the main names of xwiki "Wikipedia"
@Test public void Add_bulk_core_wikidata() {fxt.Peers_ini().Tst_add_bulk_peers("core", fxt.xwiki_("d", "www.wikidata.org", "http://www.wikidata.org/wiki/~{0}"));}
}
class Xow_xwiki_mgr_fxt {
Xow_xwiki_mgr xwiki_mgr; Xoa_lang_mgr lang_mgr; String_bldr sb = String_bldr_.new_(); Xoa_app app; Xow_wiki wiki;
public void Clear() {
if (xwiki_mgr == null) {
app = Xoa_app_fxt.app_();
wiki = Xoa_app_fxt.wiki_tst_(app);
xwiki_mgr = wiki.Xwiki_mgr();
lang_mgr = app.Lang_mgr();
}
xwiki_mgr.Clear();
lang_mgr.Clear();
}
public Xow_wiki Wiki() {return wiki;}
public Xow_xwiki_itm xwiki_null_(String key) {return new Xow_xwiki_itm(Bry_.new_utf8_(key), Bry_.Empty, Xow_wiki_domain_.Tid_other, Xol_lang_itm_.Id__unknown, Bry_.Empty);}
public Xow_xwiki_itm xwiki_(String key, String domain, String fmt) {return new Xow_xwiki_itm(Bry_.new_utf8_(key), Bry_.new_utf8_(fmt), Xow_wiki_domain_.Tid_other, Xol_lang_itm_.Id__unknown, Bry_.new_utf8_(domain));}
public Xow_xwiki_mgr_fxt Tst_add_bulk(String raw, int lang_tid, byte wiki_tid, String alias, String fmt, String domain) {
Xow_xwiki_itm itm = xwiki_mgr.Add_bulk_row(Xol_lang_itm_.Regy(), Bry_.new_ascii_(raw));
Tfds.Eq(alias, String_.new_ascii_(itm.Key()));
Tfds.Eq(fmt, String_.new_ascii_(itm.Fmt()));
Tfds.Eq(wiki_tid, itm.Wiki_tid(), "wiki_tid");
Tfds.Eq(lang_tid, itm.Lang_id(), "lang_id");
return this;
}
public Xow_xwiki_mgr_fxt Langs_ini() {
lang_mgr.Groups().Set_bulk(Bry_.new_utf8_(String_.Concat_lines_nl
( "+||grp|wiki"
, "+|wiki|grp|english"
, "+|wiki|grp|europe_west"
, "+|wiki|grp|asia_east"
, "+|english|itm|en|English"
, "+|europe_west|itm|fr|French"
, "+|europe_west|itm|de|German"
, "+|asia_east|itm|ja|Japanese"
)));
return this;
}
public Xow_xwiki_mgr_fxt Peers_ini() {
app.Wiki_mgr().Groups().Set_bulk(Bry_.new_utf8_(String_.Concat_lines_nl
( "+|core|itm|commons|commons"
, "+|core|itm|meta|meta;m"
, "+|core|itm|wikidata|d"
, "+|peer|itm|wiktionary|wikt;wiktionary"
, "+|peer|itm|wikisource|s"
, "+|peer|itm|wikipedia|w;wikipedia"
)));
return this;
}
public Xow_xwiki_mgr_fxt Tst_add_bulk_langs(String langs, Xow_xwiki_itm... itms) {
xwiki_mgr.Add_bulk_langs(Bry_.new_utf8_(langs));
Tfds.Eq_str_lines(Xto_str(itms), Xto_str(Xto_ary(itms)));
return this;
}
public Xow_xwiki_mgr_fxt Tst_add_bulk_peers(String exclude, Xow_xwiki_itm... itms) {
xwiki_mgr.Add_bulk_peers(Bry_.new_utf8_(exclude));
Tfds.Eq_str_lines(Xto_str(itms), Xto_str(Xto_ary(itms)));
return this;
}
public Xow_xwiki_mgr_fxt Tst_itms(Xow_xwiki_itm... itms) {
Tfds.Eq_str_lines(Xto_str(itms), Xto_str(Xto_ary(itms)));
return this;
}
Xow_xwiki_itm[] Xto_ary(Xow_xwiki_itm[] itms) {
int len = itms.length;
ListAdp rv = ListAdp_.new_();
for (int i = 0; i < len; i++) {
byte[] alias = itms[i].Key();
Xow_xwiki_itm itm = xwiki_mgr.Get_by_key(alias);
if (itm == null) itm = xwiki_null_(String_.new_utf8_(alias)); // "null", ignore
rv.Add(itm);
}
return (Xow_xwiki_itm[])rv.XtoAry(Xow_xwiki_itm.class);
}
String Xto_str(Xow_xwiki_itm[] itms) {
int len = itms.length;
for (int i = 0; i < len; i++) {
Xow_xwiki_itm itm = itms[i];
if (Bry_.Len_eq_0(itm.Domain())) // "null", ignore
sb.Add(itm.Key()).Add_char_nl();
else {
sb.Add(itm.Key()).Add_char_pipe().Add(itm.Domain()).Add_char_pipe().Add(itm.Fmt()).Add_char_nl();
}
}
return sb.XtoStrAndClear();
}
}