You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gnosygnu_xowa/400_xowa/src/gplx/xowa/xtns/wbases/Wdata_wiki_mgr.java

258 lines
12 KiB

/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2020 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx.xowa.xtns.wbases;
import gplx.Bool_;
import gplx.Bry_;
import gplx.Bry_bfr;
import gplx.Bry_bfr_;
import gplx.GfoMsg;
import gplx.Gfo_evt_itm;
import gplx.Gfo_evt_mgr;
import gplx.Gfo_evt_mgr_;
import gplx.Gfo_invk;
import gplx.Gfo_invk_;
import gplx.GfsCtx;
import gplx.String_;
import gplx.Yn;
import gplx.langs.jsons.Json_doc;
import gplx.langs.jsons.Json_kv;
import gplx.langs.jsons.Json_parser;
import gplx.xowa.Xoa_ttl;
import gplx.xowa.Xoae_app;
import gplx.xowa.Xoae_page;
import gplx.xowa.Xowe_wiki;
import gplx.xowa.apps.apis.xowa.html.Xoapi_toggle_mgr;
import gplx.xowa.apps.apis.xowa.xtns.Xoapi_wikibase;
import gplx.xowa.htmls.Xoh_consts;
import gplx.xowa.langs.Xol_lang_itm;
import gplx.xowa.langs.msgs.Xol_msg_itm_;
import gplx.xowa.parsers.Xop_ctx;
import gplx.xowa.parsers.logs.Xop_log_property_wkr;
import gplx.xowa.users.Xoue_user;
import gplx.xowa.wikis.domains.Xow_domain_itm;
import gplx.xowa.wikis.domains.Xow_domain_tid_;
import gplx.xowa.wikis.nss.Xow_ns_;
import gplx.xowa.xtns.wbases.claims.Wbase_claim_grp;
import gplx.xowa.xtns.wbases.claims.enums.Wbase_claim_rank_;
import gplx.xowa.xtns.wbases.claims.enums.Wbase_claim_value_type_;
import gplx.xowa.xtns.wbases.claims.itms.Wbase_claim_base;
import gplx.xowa.xtns.wbases.hwtrs.Wdata_hwtr_mgr;
import gplx.xowa.xtns.wbases.hwtrs.Wdata_hwtr_msgs;
import gplx.xowa.xtns.wbases.hwtrs.Wdata_lbl_wkr_wiki;
import gplx.xowa.xtns.wbases.parsers.Wdata_doc_parser;
import gplx.xowa.xtns.wbases.parsers.Wdata_doc_parser_v1;
import gplx.xowa.xtns.wbases.parsers.Wdata_doc_parser_v2;
import gplx.xowa.xtns.wbases.stores.Wbase_doc_mgr;
import gplx.xowa.xtns.wbases.stores.Wbase_pid_mgr;
import gplx.xowa.xtns.wbases.stores.Wbase_prop_mgr;
import gplx.xowa.xtns.wbases.stores.Wbase_prop_mgr_loader_;
import gplx.xowa.xtns.wbases.stores.Wbase_qid_mgr;
public class Wdata_wiki_mgr implements Gfo_evt_itm, Gfo_invk {
private final Xoae_app app;
private final Wdata_prop_val_visitor prop_val_visitor;
private final Wdata_doc_parser wdoc_parser_v1 = new Wdata_doc_parser_v1(), wdoc_parser_v2 = new Wdata_doc_parser_v2();
private final Object thread_lock = new Object();
private final Bry_bfr tmp_bfr = Bry_bfr_.New_w_size(32);
public Wdata_wiki_mgr(Xoae_app app) {
this.app = app;
this.evt_mgr = new Gfo_evt_mgr(this);
this.Qid_mgr = new Wbase_qid_mgr(this);
this.Pid_mgr = new Wbase_pid_mgr(this);
this.Doc_mgr = new Wbase_doc_mgr(this, this.Qid_mgr);
this.prop_mgr = new Wbase_prop_mgr(Wbase_prop_mgr_loader_.New_db(this));
this.prop_val_visitor = new Wdata_prop_val_visitor(app, this);
this.Enabled_(true);
}
public Gfo_evt_mgr Evt_mgr() {return evt_mgr;} private final Gfo_evt_mgr evt_mgr;
public final Wbase_qid_mgr Qid_mgr;
public final Wbase_pid_mgr Pid_mgr;
public final Wbase_doc_mgr Doc_mgr;
public Wbase_prop_mgr Prop_mgr() {return prop_mgr;} private final Wbase_prop_mgr prop_mgr;
public boolean Enabled() {return enabled;} private boolean enabled;
public void Enabled_(boolean v) {
this.enabled = v;
Qid_mgr.Enabled_(v);
Pid_mgr.Enabled_(v);
Doc_mgr.Enabled_(v);
}
public byte[] Domain() {return domain;} public void Domain_(byte[] v) {domain = v;} private byte[] domain = Bry_.new_a7("www.wikidata.org");
public Wdata_hwtr_mgr Hwtr_mgr() {
if (hwtr_mgr == null)
Hwtr_mgr_assert();
return hwtr_mgr;
} private Wdata_hwtr_mgr hwtr_mgr;
public Xowe_wiki Wdata_wiki() {
if (wdata_wiki == null) {
synchronized (thread_lock) { // LOCK:must synchronized b/c multiple threads may init wdata_mgr at same time;
Xowe_wiki tmp_wdata_wiki = app.Wiki_mgr().Get_by_or_make(domain).Init_assert();
if (wdata_wiki == null) // synchronized is not around "if (wdata_wiki == null)", so multiple threads may try to set; only set if null; DATE:2016-09-12
wdata_wiki = tmp_wdata_wiki;
}
}
return wdata_wiki;
} private Xowe_wiki wdata_wiki;
public Json_parser Jdoc_parser() {return jdoc_parser;} private Json_parser jdoc_parser = new Json_parser();
public void Init_by_app() {}
public Wdata_doc_parser Wdoc_parser(Json_doc jdoc) {
Json_kv itm_0 = Json_kv.Cast(jdoc.Root_nde().Get_at(0)); // get 1st node
return Bry_.Eq(itm_0.Key().Data_bry(), Wdata_doc_parser_v2.Bry_type)
|| Bry_.Eq(itm_0.Key().Data_bry(), Wdata_doc_parser_v2.Bry_id)
? wdoc_parser_v2 : wdoc_parser_v1; // if "type", must be v2
}
public Xop_log_property_wkr Property_wkr() {return property_wkr;} private Xop_log_property_wkr property_wkr;
public void Clear() {
synchronized (thread_lock) { // LOCK:app-level
Qid_mgr.Clear();
Pid_mgr.Clear();
Doc_mgr.Clear();
}
}
public byte[] Get_claim_or(Xow_domain_itm domain, Xoa_ttl page_ttl, int pid, byte[] or) {
byte[] qid = this.Qid_mgr.Get_qid_or_null(domain.Abrv_wm(), page_ttl); if (qid == null) return or;
Wdata_doc wdoc = Doc_mgr.Get_by_loose_id_or_null(qid); if (wdoc == null) return or;
Wbase_claim_grp claim_grp = wdoc.Get_claim_grp_or_null(pid);
if (claim_grp == null || claim_grp.Len() == 0) return or;
Wbase_claim_base claim_itm = claim_grp.Get_at(0);
Resolve_claim(tmp_bfr, domain, claim_itm);
return tmp_bfr.To_bry_and_clear();
}
public void Resolve_claim(Bry_bfr rv, Xow_domain_itm domain, Wbase_claim_base claim_itm) {
synchronized (thread_lock) { // LOCK:must synchronized b/c prop_val_visitor has member bfr which can get overwritten; DATE:2016-07-06
if (hwtr_mgr == null) Hwtr_mgr_assert();
prop_val_visitor.Init(rv, hwtr_mgr.Msgs(), domain.Lang_orig_key(), Bool_.N);
claim_itm.Welcome(prop_val_visitor);
}
}
public void Resolve_to_bfr(Bry_bfr bfr, Xowe_wiki wiki, Wbase_claim_grp prop_grp, byte[] lang_key, boolean mode_is_statements) {
synchronized (thread_lock) { // LOCK:must synchronized b/c prop_val_visitor has member bfr which can get overwritten; DATE:2016-07-06
if (hwtr_mgr == null) Hwtr_mgr_assert();
int len = prop_grp.Len();
Wbase_claim_base selected = null;
for (int i = 0; i < len; i++) { // NOTE: multiple props possible; EX: {{#property:P1082}}; PAGE:en.w:Earth DATE:2015-08-02
Wbase_claim_base prop = prop_grp.Get_at(i);
if (selected == null) selected = prop; // if selected not set, set it; will always set to 1st prop
if (prop.Rank_tid() == Wbase_claim_rank_.Tid__preferred) { // if prop is preferred, select it and exit;
selected = prop;
break;
}
}
switch (selected.Snak_tid()) { // SEE:NOTE:novalue/somevalue
case Wbase_claim_value_type_.Tid__novalue:
bfr.Add(wiki.Msg_mgr().Val_by_id(Xol_msg_itm_.Id_xowa_wikidata_novalue));
break;
case Wbase_claim_value_type_.Tid__somevalue:
bfr.Add(wiki.Msg_mgr().Val_by_id(Xol_msg_itm_.Id_xowa_wikidata_somevalue));
break;
default: {
prop_val_visitor.Init(bfr, hwtr_mgr.Msgs(), lang_key, mode_is_statements);
selected.Welcome(prop_val_visitor);
break;
}
}
}
}
public byte[] Popup_text(Xoae_page page) {
Hwtr_mgr_assert();
Wdata_doc wdoc = Doc_mgr.Get_by_exact_id_or_null(page.Ttl().Full_db());
if (wdoc == null) return Bry_.Empty;
return hwtr_mgr.Popup(wdoc);
}
public void Write_json_as_html(Bry_bfr bfr, Xoa_ttl page_ttl, byte[] data_raw) {
Hwtr_mgr_assert();
Wdata_doc wdoc = Doc_mgr.Get_by_exact_id_or_null(page_ttl.Full_db());
if (wdoc == null) return;
hwtr_mgr.Init_by_wdoc(wdoc);
bfr.Add(hwtr_mgr.Write(wdoc));
}
private void Hwtr_mgr_assert() {
if (hwtr_mgr != null) return;
Xoapi_toggle_mgr toggle_mgr = app.Api_root().Html().Page().Toggle_mgr();
Xoapi_wikibase wikibase_api = app.Api_root().Xtns().Wikibase();
hwtr_mgr = new Wdata_hwtr_mgr();
hwtr_mgr.Init_by_ctor(wikibase_api, this, new Wdata_lbl_wkr_wiki(wikibase_api, this), gplx.langs.htmls.encoders.Gfo_url_encoder_.Href, toggle_mgr, app.Usere().Wiki().Xwiki_mgr());
this.Hwtr_msgs_make();
Gfo_evt_mgr_.Sub_same_many(app.Usere(), this, Xoue_user.Evt_lang_changed);
}
private void Hwtr_msgs_make() {
// if (!app.Wiki_mgr().Wiki_regy().Has(Xow_domain_itm_.Bry__wikidata)) return; // DELETE: don't know why guard is needed; breaks test; DATE:2016-10-20
Xol_lang_itm new_lang = app.Usere().Lang();
Xowe_wiki cur_wiki = this.Wdata_wiki();
cur_wiki.Xtn_mgr().Xtn_wikibase().Load_msgs(cur_wiki, new_lang);
Wdata_hwtr_msgs hwtr_msgs = Wdata_hwtr_msgs.new_(cur_wiki.Msg_mgr());
hwtr_mgr.Init_by_lang(new_lang, hwtr_msgs);
}
public static void Write_json_as_html(Json_parser jdoc_parser, Bry_bfr bfr, byte[] data_raw) {
bfr.Add(Xoh_consts.Span_bgn_open).Add(Xoh_consts.Id_atr).Add(Html_json_id).Add(Xoh_consts.__end_quote); // <span id="xowa-wikidata-json">
Json_doc json = jdoc_parser.Parse(data_raw);
json.Root_nde().Print_as_json(bfr, 0);
bfr.Add(Xoh_consts.Span_end);
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_enabled)) return Yn.To_str(enabled);
else if (ctx.Match(k, Invk_enabled_)) enabled = m.ReadYn("v");
else if (ctx.Match(k, Invk_domain)) return String_.new_u8(domain);
else if (ctx.Match(k, Invk_domain_)) domain = m.ReadBry("v");
else if (ctx.Match(k, Invk_property_wkr)) return m.ReadYnOrY("v") ? Property_wkr_or_new() : Gfo_invk_.Noop;
else if (ctx.Match(k, Xoue_user.Evt_lang_changed)) Hwtr_msgs_make();
else return Gfo_invk_.Rv_unhandled;
return this;
}
private static final String Invk_enabled = "enabled", Invk_enabled_ = "enabled_", Invk_domain = "domain", Invk_domain_ = "domain_", Invk_property_wkr = "property_wkr";
public Xop_log_property_wkr Property_wkr_or_new() {
if (property_wkr == null) property_wkr = app.Log_mgr().Make_wkr_property();
return property_wkr;
}
public static final int Ns_property = 120;
public static final String Ns_property_name = "Property";
public static final byte[] Ns_property_name_bry = Bry_.new_a7(Ns_property_name);
public static final int Ns_lexeme = 146;
public static final String Ns_lexeme_name = "Lexeme";
public static final byte[] Ns_lexeme_name_bry = Bry_.new_a7(Ns_lexeme_name);
public static final byte[] Html_json_id = Bry_.new_a7("xowa-wikidata-json");
public static boolean Wiki_page_is_json(int wiki_tid, int ns_id) {
switch (wiki_tid) {
case Xow_domain_tid_.Tid__wikidata:
switch (ns_id) {
case Xow_ns_.Tid__main:
case Wdata_wiki_mgr.Ns_property:
case Wdata_wiki_mgr.Ns_lexeme:
return true;
default:
return false;
}
case Xow_domain_tid_.Tid__home:
if (ns_id == gplx.xowa.xtns.wbases.Wdata_wiki_mgr.Ns_property)
return true;
break;
}
return false;
}
public static void Log_missing_qid(Xop_ctx ctx, String type, byte[] id) {
if (id == null) id = Bry_.Empty;
ctx.Wiki().Appe().Usr_dlg().Log_many("", "", "Unknown id in wikidata; type=~{0} id=~{1} page=~{2}", type, id, ctx.Page().Url_bry_safe());
}
}
/*
NOTE:novalue/somevalue
Rough approximation of wikibase logic which is more involved with its different SnakFormatters
* https://github.com/wikimedia/mediawiki-extensions-Wikibase/blob/master/lib/includes/Formatters/OutputFormatSnakFormatterFactory.php: formatter factory; note lines for somevalue / novalue
* https://github.com/wikimedia/mediawiki-extensions-Wikibase/blob/master/lib/includes/Formatters/MessageSnakFormatter.php: formatter definition
* https://github.com/wikimedia/mediawiki-extensions-Wikibase/blob/master/repo/i18n/en.json: message definitions
*/