mirror of
https://github.com/gnosygnu/xowa.git
synced 2024-10-27 20:34:16 +00:00
Wikibase: Add getReferencedEntityId; refactor some wikibase code
This commit is contained in:
parent
6348aa6177
commit
341d2e13a4
@ -15,8 +15,8 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
|||||||
*/
|
*/
|
||||||
package gplx.xowa.apps.caches; import gplx.*; import gplx.xowa.*; import gplx.xowa.apps.*;
|
package gplx.xowa.apps.caches; import gplx.*; import gplx.xowa.*; import gplx.xowa.apps.*;
|
||||||
import gplx.xowa.xtns.wbases.*;
|
import gplx.xowa.xtns.wbases.*;
|
||||||
public class Wdata_doc_cache {
|
public class Wbase_doc_cache {
|
||||||
private Hash_adp_bry hash = Hash_adp_bry.cs();
|
private final Hash_adp_bry hash = Hash_adp_bry.cs();
|
||||||
public void Add(byte[] qid, Wdata_doc doc) {hash.Add(qid, doc);}
|
public void Add(byte[] qid, Wdata_doc doc) {hash.Add(qid, doc);}
|
||||||
public Wdata_doc Get_or_null(byte[] qid) {return (Wdata_doc)hash.Get_by_bry(qid);}
|
public Wdata_doc Get_or_null(byte[] qid) {return (Wdata_doc)hash.Get_by_bry(qid);}
|
||||||
public void Free_mem_all() {this.Clear();}
|
public void Free_mem_all() {this.Clear();}
|
@ -15,7 +15,7 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
|||||||
*/
|
*/
|
||||||
package gplx.xowa.apps.caches; import gplx.*; import gplx.xowa.*; import gplx.xowa.apps.*;
|
package gplx.xowa.apps.caches; import gplx.*; import gplx.xowa.*; import gplx.xowa.apps.*;
|
||||||
public class Xoa_cache_mgr {
|
public class Xoa_cache_mgr {
|
||||||
public Wdata_doc_cache Doc_cache() {return doc_cache;} private Wdata_doc_cache doc_cache = new Wdata_doc_cache();
|
public Wbase_doc_cache Doc_cache() {return doc_cache;} private Wbase_doc_cache doc_cache = new Wbase_doc_cache();
|
||||||
public void Free_mem_all() {
|
public void Free_mem_all() {
|
||||||
doc_cache.Free_mem_all();
|
doc_cache.Free_mem_all();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 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.scribunto.libs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.scribunto.*;
|
||||||
|
import gplx.xowa.xtns.wbases.*; import gplx.xowa.xtns.wbases.claims.*; import gplx.xowa.xtns.wbases.claims.itms.*; import gplx.xowa.xtns.wbases.claims.enums.*;
|
||||||
|
// REF: https://github.com/wmde/WikibaseDataModelServices/blob/master/src/Lookup/EntityRetrievingClosestReferencedEntityIdLookup.php
|
||||||
|
class Referenced_entity_lookup_wkr {
|
||||||
|
private final Wbase_doc_mgr entity_mgr;
|
||||||
|
private final int maxDepth;
|
||||||
|
private final int maxEntityVisits;
|
||||||
|
private final Xoa_url url;
|
||||||
|
private final byte[] fromId;
|
||||||
|
private final int propertyId;
|
||||||
|
private final Ordered_hash toIds;
|
||||||
|
private final Ordered_hash alreadyVisited = Ordered_hash_.New_bry();
|
||||||
|
private final List_adp tmp_snak_list = List_adp_.New();
|
||||||
|
public Referenced_entity_lookup_wkr(int maxDepth, int maxEntityVisits, Wbase_doc_mgr entity_mgr, Xoa_url url, byte[] fromId, int propertyId, Ordered_hash toIds) {
|
||||||
|
this.maxDepth = maxDepth;
|
||||||
|
this.maxEntityVisits = maxEntityVisits;
|
||||||
|
this.entity_mgr = entity_mgr;
|
||||||
|
this.url = url;
|
||||||
|
this.fromId = fromId;
|
||||||
|
this.propertyId = propertyId;
|
||||||
|
this.toIds = toIds;
|
||||||
|
}
|
||||||
|
public byte[] Get_referenced_entity() {
|
||||||
|
if (toIds == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
int steps = this.maxDepth + 1;// Add one as checking $fromId already is a step
|
||||||
|
Ordered_hash toVisit = Ordered_hash_.New_bry();
|
||||||
|
toVisit.Add_as_key_and_val(fromId);
|
||||||
|
|
||||||
|
while (steps-- > 0) {
|
||||||
|
// $this->entityPrefetcher->prefetch( $toVisit );
|
||||||
|
Ordered_hash toVisitNext = Ordered_hash_.New_bry();
|
||||||
|
int toVisitLen = toVisit.Len();
|
||||||
|
for (int i = 0; i < toVisitLen; i++) {
|
||||||
|
byte[] curId = (byte[])toVisit.Get_at(i);
|
||||||
|
byte[] result = processEntityById(alreadyVisited, curId, fromId, propertyId, toIds, toVisitNext);
|
||||||
|
if (result != null)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
// Remove already visited entities
|
||||||
|
toVisit = merge(toVisitNext, alreadyVisited);
|
||||||
|
if (toVisit.Len() == 0)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// Exhausted the max. depth without finding anything.
|
||||||
|
throw newErr(true);
|
||||||
|
}
|
||||||
|
private Err newErr(boolean isMaxDepthOrMaxEntities) {
|
||||||
|
return Err_.new_wo_type("max exceeded", "type", isMaxDepthOrMaxEntities ? "depth" : "entities", "url", url.To_bry(true, false), "fromId", fromId, "propertyId", propertyId, "toIds", toString(toIds));
|
||||||
|
}
|
||||||
|
private static String toString(Ordered_hash hash) {
|
||||||
|
Bry_bfr bfr = Bry_bfr_.New();
|
||||||
|
int len = hash.Len();
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
bfr.Add_str_u8(Object_.Xto_str_strict_or_null_mark(hash.Get_at(i))).Add_byte_pipe();
|
||||||
|
}
|
||||||
|
return bfr.To_str_and_clear();
|
||||||
|
}
|
||||||
|
private byte[] processEntityById(Ordered_hash alreadyVisited, byte[] id, byte[] fromId, int propertyId, Ordered_hash toIds, Ordered_hash toVisit) {
|
||||||
|
Wdata_doc entity = getEntity(alreadyVisited, id, fromId, propertyId, toIds);
|
||||||
|
if (entity == null)
|
||||||
|
return null;
|
||||||
|
Wbase_claim_base[] mainSnaks = getMainSnaks(entity, propertyId);
|
||||||
|
for (Wbase_claim_base mainSnak : mainSnaks) {
|
||||||
|
byte[] result = processSnak(mainSnak, toVisit, toIds);
|
||||||
|
if (result != null)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
private Wdata_doc getEntity(Ordered_hash alreadyVisited, byte[] id, byte[] fromId, int propertyId, Ordered_hash toIds) {
|
||||||
|
if (alreadyVisited.Has(id)) {
|
||||||
|
Gfo_usr_dlg_.Instance.Warn_many("", "", "Entity " + String_.new_u8(id) + " already visited");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
alreadyVisited.Add_as_key_and_val(id);
|
||||||
|
if (alreadyVisited.Len() > maxEntityVisits)
|
||||||
|
throw newErr(false);
|
||||||
|
return entity_mgr.Get_by_bry_or_null(id);
|
||||||
|
}
|
||||||
|
private Wbase_claim_base[] getMainSnaks(Wdata_doc entity, int propertyId) {
|
||||||
|
Wbase_claim_grp claims = entity.Claim_list_get(propertyId);
|
||||||
|
return claims.Get_best(tmp_snak_list);
|
||||||
|
}
|
||||||
|
private byte[] processSnak(Wbase_claim_base snak, Ordered_hash toVisit, Ordered_hash toIds) {
|
||||||
|
if (snak.Val_tid() != Wbase_claim_type_.Tid__entity)
|
||||||
|
return null;
|
||||||
|
Wbase_claim_entity snakEntity = (Wbase_claim_entity)snak;
|
||||||
|
byte[] entityId = snakEntity.Page_ttl_db();
|
||||||
|
if (toIds.Has(entityId))
|
||||||
|
return entityId;
|
||||||
|
toVisit.Add_as_key_and_val(entityId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Ordered_hash merge(Ordered_hash toVisitNext, Ordered_hash alreadyVisited) {
|
||||||
|
int len = alreadyVisited.Len();
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
byte[] bry = (byte[])alreadyVisited.Get_at(i);
|
||||||
|
if (toVisitNext.Has(bry))
|
||||||
|
toVisitNext.Del(bry);
|
||||||
|
}
|
||||||
|
return toVisitNext;
|
||||||
|
}
|
||||||
|
}
|
@ -20,6 +20,7 @@ import gplx.xowa.xtns.scribunto.procs.*;
|
|||||||
import gplx.xowa.xtns.wbases.mediawiki.client.includes.*; import gplx.xowa.xtns.wbases.mediawiki.client.includes.dataAccess.scribunto.*;
|
import gplx.xowa.xtns.wbases.mediawiki.client.includes.*; import gplx.xowa.xtns.wbases.mediawiki.client.includes.dataAccess.scribunto.*;
|
||||||
public class Scrib_lib_wikibase implements Scrib_lib {
|
public class Scrib_lib_wikibase implements Scrib_lib {
|
||||||
private final Scrib_core core;
|
private final Scrib_core core;
|
||||||
|
private Wbase_doc_mgr entity_mgr;
|
||||||
private Wbase_entity_accessor entity_accessor;
|
private Wbase_entity_accessor entity_accessor;
|
||||||
private WikibaseLanguageIndependentLuaBindings wikibaseLanguageIndependentLuaBindings;
|
private WikibaseLanguageIndependentLuaBindings wikibaseLanguageIndependentLuaBindings;
|
||||||
private Scrib_lua_proc notify_page_changed_fnc;
|
private Scrib_lua_proc notify_page_changed_fnc;
|
||||||
@ -28,9 +29,9 @@ public class Scrib_lib_wikibase implements Scrib_lib {
|
|||||||
public Scrib_proc_mgr Procs() {return procs;} private final Scrib_proc_mgr procs = new Scrib_proc_mgr();
|
public Scrib_proc_mgr Procs() {return procs;} private final Scrib_proc_mgr procs = new Scrib_proc_mgr();
|
||||||
public Scrib_lib Init() {
|
public Scrib_lib Init() {
|
||||||
procs.Init_by_lib(this, Proc_names);
|
procs.Init_by_lib(this, Proc_names);
|
||||||
Wbase_doc_mgr entityMgr = core.App().Wiki_mgr().Wdata_mgr().Doc_mgr;
|
this.entity_mgr = core.App().Wiki_mgr().Wdata_mgr().Doc_mgr;
|
||||||
this.entity_accessor = new Wbase_entity_accessor(entityMgr);
|
this.entity_accessor = new Wbase_entity_accessor(entity_mgr);
|
||||||
this.wikibaseLanguageIndependentLuaBindings = new WikibaseLanguageIndependentLuaBindings(entityMgr);
|
this.wikibaseLanguageIndependentLuaBindings = new WikibaseLanguageIndependentLuaBindings(entity_mgr);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public Scrib_lib Clone_lib(Scrib_core core) {return new Scrib_lib_wikibase(core);}
|
public Scrib_lib Clone_lib(Scrib_core core) {return new Scrib_lib_wikibase(core);}
|
||||||
@ -97,11 +98,14 @@ public class Scrib_lib_wikibase implements Scrib_lib {
|
|||||||
entityId = Bry_.Mid(entityId, colonPos + 1);
|
entityId = Bry_.Mid(entityId, colonPos + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean valid = checkEntityIdOrNull(entityId) != null;
|
||||||
|
return rslt.Init_obj(valid);
|
||||||
|
}
|
||||||
|
private static byte[] checkEntityIdOrNull(byte[] entityId) {
|
||||||
/* REF: https://github.com/wmde/WikibaseDataModel/tree/master/src/Entity/
|
/* REF: https://github.com/wmde/WikibaseDataModel/tree/master/src/Entity/
|
||||||
PropertyId.php.PATTERN: '/^P[1-9]\d{0,9}\z/i';
|
PropertyId.php.PATTERN: '/^P[1-9]\d{0,9}\z/i';
|
||||||
ItemId.php.PATTERN : '/^Q[1-9]\d{0,9}\z/i';
|
ItemId.php.PATTERN : '/^Q[1-9]\d{0,9}\z/i';
|
||||||
*/
|
*/
|
||||||
boolean valid = false;
|
|
||||||
if (entityId.length > 0) {
|
if (entityId.length > 0) {
|
||||||
switch (entityId[0]) {
|
switch (entityId[0]) {
|
||||||
case Byte_ascii.Ltr_P:
|
case Byte_ascii.Ltr_P:
|
||||||
@ -122,14 +126,14 @@ public class Scrib_lib_wikibase implements Scrib_lib {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (numeric)
|
if (numeric)
|
||||||
valid = true;
|
return entityId;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rslt.Init_obj(valid);
|
return null;
|
||||||
}
|
}
|
||||||
public boolean GetEntityId(Scrib_proc_args args, Scrib_proc_rslt rslt) {
|
public boolean GetEntityId(Scrib_proc_args args, Scrib_proc_rslt rslt) {
|
||||||
byte[] ttl_bry = args.Pull_bry(0);
|
byte[] ttl_bry = args.Pull_bry(0);
|
||||||
@ -138,8 +142,21 @@ public class Scrib_lib_wikibase implements Scrib_lib {
|
|||||||
byte[] rv = wiki.Appe().Wiki_mgr().Wdata_mgr().Qid_mgr.Get_or_null(wiki, ttl); if (rv == null) rv = Bry_.Empty;
|
byte[] rv = wiki.Appe().Wiki_mgr().Wdata_mgr().Qid_mgr.Get_or_null(wiki, ttl); if (rv == null) rv = Bry_.Empty;
|
||||||
return rslt.Init_obj(rv);
|
return rslt.Init_obj(rv);
|
||||||
}
|
}
|
||||||
|
// REF: https://github.com/wikimedia/mediawiki-extensions-Wikibase/blob/master/client/config/WikibaseClient.default.php
|
||||||
|
private static final int ReferencedEntityIdMaxDepth = 4, ReferencedEntityIdMaxReferencedEntityVisits = 50;
|
||||||
|
// private static final int ReferencedEntityIdAccessLimit = 3; // max # of calls per page?
|
||||||
public boolean GetReferencedEntityId(Scrib_proc_args args, Scrib_proc_rslt rslt) {
|
public boolean GetReferencedEntityId(Scrib_proc_args args, Scrib_proc_rslt rslt) {
|
||||||
throw Err_.new_unimplemented();
|
// get fromId, propertyId, and toIds
|
||||||
|
byte[] fromId = checkEntityIdOrNull(args.Pull_bry(0));
|
||||||
|
byte[] propertyIdBry = checkEntityIdOrNull(args.Pull_bry(1));
|
||||||
|
int propertyId = Bry_.To_int(Bry_.Mid(propertyIdBry, 1));
|
||||||
|
Keyval[] toIdsAry = args.Pull_kv_ary_safe(2);
|
||||||
|
Ordered_hash toIds = Ordered_hash_.New_bry();
|
||||||
|
for (Keyval kv : toIdsAry) {
|
||||||
|
toIds.Add_as_key_and_val(checkEntityIdOrNull(Bry_.new_u8((String)kv.Val())));
|
||||||
|
}
|
||||||
|
Referenced_entity_lookup_wkr wkr = new Referenced_entity_lookup_wkr(ReferencedEntityIdMaxDepth, ReferencedEntityIdMaxReferencedEntityVisits, entity_mgr, core.Page().Url(), fromId, propertyId, toIds);
|
||||||
|
return rslt.Init_obj(wkr.Get_referenced_entity());
|
||||||
}
|
}
|
||||||
public boolean EntityExists(Scrib_proc_args args, Scrib_proc_rslt rslt) {
|
public boolean EntityExists(Scrib_proc_args args, Scrib_proc_rslt rslt) {
|
||||||
Wdata_doc wdoc = Get_wdoc_or_null(args, core, false);
|
Wdata_doc wdoc = Get_wdoc_or_null(args, core, false);
|
||||||
@ -238,12 +255,12 @@ public function formatValues( $snaksSerialization ) {
|
|||||||
public boolean IncrementExpensiveFunctionCount(Scrib_proc_args args, Scrib_proc_rslt rslt) {
|
public boolean IncrementExpensiveFunctionCount(Scrib_proc_args args, Scrib_proc_rslt rslt) {
|
||||||
return rslt.Init_obj(Keyval_.Ary_empty); // NOTE: for now, always return null (XOWA does not care about expensive parser functions)
|
return rslt.Init_obj(Keyval_.Ary_empty); // NOTE: for now, always return null (XOWA does not care about expensive parser functions)
|
||||||
}
|
}
|
||||||
private static Wdata_doc Get_wdoc_or_null(Scrib_proc_args args, Scrib_core core, boolean logMissing) {
|
public Wdata_doc Get_wdoc_or_null(Scrib_proc_args args, Scrib_core core, boolean logMissing) {
|
||||||
// get qid / pid from scrib_arg[0]; if none, return null;
|
// get qid / pid from scrib_arg[0]; if none, return null;
|
||||||
byte[] xid_bry = args.Pull_bry(0); if (Bry_.Len_eq_0(xid_bry)) return null; // NOTE: some Modules do not pass in an argument; return early, else spurious warning "invalid qid for ttl" (since ttl is blank); EX:w:Module:Authority_control; DATE:2013-10-27
|
byte[] xid_bry = args.Pull_bry(0); if (Bry_.Len_eq_0(xid_bry)) return null; // NOTE: some Modules do not pass in an argument; return early, else spurious warning "invalid qid for ttl" (since ttl is blank); EX:w:Module:Authority_control; DATE:2013-10-27
|
||||||
|
|
||||||
// get wdoc
|
// get wdoc
|
||||||
Wdata_doc wdoc = core.Wiki().Appe().Wiki_mgr().Wdata_mgr().Doc_mgr.Get_by_xid_or_null(xid_bry); // NOTE: by_xid b/c Module passes just "p1" not "Property:P1"
|
Wdata_doc wdoc = entity_mgr.Get_by_xid_or_null(xid_bry); // NOTE: by_xid b/c Module passes just "p1" not "Property:P1"
|
||||||
if (wdoc == null && logMissing) Wdata_wiki_mgr.Log_missing_qid(core.Ctx(), xid_bry);
|
if (wdoc == null && logMissing) Wdata_wiki_mgr.Log_missing_qid(core.Ctx(), xid_bry);
|
||||||
return wdoc;
|
return wdoc;
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,21 @@ public class Scrib_lib_wikibase_tst {
|
|||||||
fxt.Test_scrib_proc_str(lib, Scrib_lib_wikibase.Invk_getEntityId, Object_.Ary("Earth" ), "q2");
|
fxt.Test_scrib_proc_str(lib, Scrib_lib_wikibase.Invk_getEntityId, Object_.Ary("Earth" ), "q2");
|
||||||
fxt.Test_scrib_proc_str(lib, Scrib_lib_wikibase.Invk_getEntityId, Object_.Ary("missing_page" ), "");
|
fxt.Test_scrib_proc_str(lib, Scrib_lib_wikibase.Invk_getEntityId, Object_.Ary("missing_page" ), "");
|
||||||
}
|
}
|
||||||
|
@Test public void GetReferencedEntityId() {
|
||||||
|
/*
|
||||||
|
wdata_fxt.Init__docs__add(wdata_fxt.Wdoc_bldr("q1").Xto_wdoc());
|
||||||
|
wdata_fxt.Init__docs__add(wdata_fxt.Wdoc_bldr("q2").Add_claims(wdata_fxt.Make_claim_entity_qid(1, 1)).Xto_wdoc());
|
||||||
|
wdata_fxt.Init__docs__add(wdata_fxt.Wdoc_bldr("q3").Add_claims(wdata_fxt.Make_claim_entity_qid(1, 2)).Xto_wdoc());
|
||||||
|
fxt.Test_scrib_proc_str(lib, Scrib_lib_wikibase.Invk_getReferencedEntityId, Object_.Ary("Q3", "P1", NewToIds("Q1")), "Q1");
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
private static Keyval[] NewToIds(String... toIds) {
|
||||||
|
int len = toIds.length;
|
||||||
|
Keyval[] rv = new Keyval[len];
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
rv[i] = Keyval_.int_(i, toIds[i]);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
@Test public void GetLabel__cur() {
|
@Test public void GetLabel__cur() {
|
||||||
wdata_fxt.Init__docs__add(wdata_fxt.Wdoc_bldr("q2").Add_label("zh-hans", "s").Add_label("zh-hant", "t").Xto_wdoc());
|
wdata_fxt.Init__docs__add(wdata_fxt.Wdoc_bldr("q2").Add_label("zh-hans", "s").Add_label("zh-hant", "t").Xto_wdoc());
|
||||||
fxt.Test_scrib_proc_str(lib, Scrib_lib_wikibase.Invk_getLabel, Object_.Ary("q2"), "s"); // do not get fallback
|
fxt.Test_scrib_proc_str(lib, Scrib_lib_wikibase.Invk_getLabel, Object_.Ary("q2"), "s"); // do not get fallback
|
||||||
|
@ -16,25 +16,26 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
|||||||
package gplx.xowa.xtns.wbases; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
package gplx.xowa.xtns.wbases; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||||
import gplx.langs.jsons.*;
|
import gplx.langs.jsons.*;
|
||||||
import gplx.xowa.wikis.pages.*;
|
import gplx.xowa.wikis.pages.*;
|
||||||
|
import gplx.xowa.apps.caches.*;
|
||||||
public class Wbase_doc_mgr {
|
public class Wbase_doc_mgr {
|
||||||
private final Xoae_app app;
|
private final Xoae_app app;
|
||||||
private final Wdata_wiki_mgr wbase_mgr;
|
private final Wdata_wiki_mgr wbase_mgr;
|
||||||
private final Wbase_qid_mgr qid_mgr;
|
private final Wbase_qid_mgr qid_mgr;
|
||||||
private final gplx.xowa.apps.caches.Wdata_doc_cache hash;
|
private final Wbase_doc_cache doc_cache;
|
||||||
public Wbase_doc_mgr(Xoae_app app, Wdata_wiki_mgr wbase_mgr, Wbase_qid_mgr qid_mgr) {
|
public Wbase_doc_mgr(Xoae_app app, Wdata_wiki_mgr wbase_mgr, Wbase_qid_mgr qid_mgr) {
|
||||||
this.app = app; this.wbase_mgr = wbase_mgr; this.qid_mgr = qid_mgr;
|
this.app = app; this.wbase_mgr = wbase_mgr; this.qid_mgr = qid_mgr;
|
||||||
this.hash = app.Cache_mgr().Doc_cache();
|
this.doc_cache = app.Cache_mgr().Doc_cache();
|
||||||
}
|
}
|
||||||
public void Enabled_(boolean v) {this.enabled = v;} private boolean enabled;
|
public void Enabled_(boolean v) {this.enabled = v;} private boolean enabled;
|
||||||
public void Clear() {
|
public void Clear() {
|
||||||
synchronized (hash) { // LOCK:app-level
|
synchronized (doc_cache) { // LOCK:app-level
|
||||||
hash.Clear();
|
doc_cache.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void Add(byte[] full_db, Wdata_doc page) { // TEST:
|
public void Add(byte[] full_db, Wdata_doc page) { // TEST:
|
||||||
synchronized (hash) { // LOCK:app-level
|
synchronized (doc_cache) { // LOCK:app-level
|
||||||
if (hash.Get_or_null(full_db) == null)
|
if (doc_cache.Get_or_null(full_db) == null)
|
||||||
hash.Add(full_db, page);
|
doc_cache.Add(full_db, page);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public Wdata_doc Get_by_ttl_or_null(Xowe_wiki wiki, Xoa_ttl ttl) {
|
public Wdata_doc Get_by_ttl_or_null(Xowe_wiki wiki, Xoa_ttl ttl) {
|
||||||
@ -43,18 +44,18 @@ public class Wbase_doc_mgr {
|
|||||||
}
|
}
|
||||||
public Wdata_doc Get_by_xid_or_null(byte[] xid) {return Get_by_bry_or_null(Prepend_property_if_needed(xid));}// scribunto passes either p1 or q1; convert p1 to "Property:P1"
|
public Wdata_doc Get_by_xid_or_null(byte[] xid) {return Get_by_bry_or_null(Prepend_property_if_needed(xid));}// scribunto passes either p1 or q1; convert p1 to "Property:P1"
|
||||||
public Wdata_doc Get_by_bry_or_null(byte[] ttl_bry) {// must be correct format; EX:"Q2" or "Property:P1"
|
public Wdata_doc Get_by_bry_or_null(byte[] ttl_bry) {// must be correct format; EX:"Q2" or "Property:P1"
|
||||||
Wdata_doc rv = hash.Get_or_null(ttl_bry);
|
Wdata_doc rv = doc_cache.Get_or_null(ttl_bry);
|
||||||
if (rv == null) {
|
if (rv == null) {
|
||||||
synchronized (hash) { // LOCK:app-level; hash;
|
synchronized (doc_cache) { // LOCK:app-level; doc_cache;
|
||||||
rv = Load_wdoc_or_null(ttl_bry); if (rv == null) return null; // page not found
|
rv = Load_wdoc_or_null(ttl_bry); if (rv == null) return null; // page not found
|
||||||
Add(ttl_bry, rv);// NOTE: use ttl_bry, not rv.Qid; allows subsequent lookups to skip this redirect cycle
|
Add(ttl_bry, rv);// NOTE: use ttl_bry, not rv.Qid; allows subsequent lookups to skip this redirect cycle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
public Wdata_doc Load_wdoc_or_null(byte[] src_ttl_bry) {
|
private Wdata_doc Load_wdoc_or_null(byte[] src_ttl_bry) {
|
||||||
if (!enabled) return null;
|
if (!enabled) return null;
|
||||||
synchronized (hash) { // LOCK:app-level; jdoc_parser; moved synchronized higher up; DATE:2016-09-03
|
synchronized (doc_cache) { // LOCK:app-level; jdoc_parser; moved synchronized higher up; DATE:2016-09-03
|
||||||
byte[] cur_ttl_bry = src_ttl_bry;
|
byte[] cur_ttl_bry = src_ttl_bry;
|
||||||
int load_count = -1;
|
int load_count = -1;
|
||||||
while (load_count < 2) { // limit to 2 tries (i.e.: 1 redirect)
|
while (load_count < 2) { // limit to 2 tries (i.e.: 1 redirect)
|
||||||
|
@ -25,7 +25,7 @@ public class Wbase_doc_mgr__tst {
|
|||||||
fxt.Parser_fxt().Init_page_create(wbase_mgr.Wdata_wiki(), "Q2", Json_doc.Make_str_by_apos("{'entity':'q2','links':{'enwiki':'q2_en','dewiki':'q2_de'}}"));
|
fxt.Parser_fxt().Init_page_create(wbase_mgr.Wdata_wiki(), "Q2", Json_doc.Make_str_by_apos("{'entity':'q2','links':{'enwiki':'q2_en','dewiki':'q2_de'}}"));
|
||||||
|
|
||||||
// fetch Q1; assert Q2 comes back
|
// fetch Q1; assert Q2 comes back
|
||||||
Wdata_doc actl = wbase_mgr.Doc_mgr.Load_wdoc_or_null(Bry_.new_u8("Q1"));
|
Wdata_doc actl = wbase_mgr.Doc_mgr.Get_by_bry_or_null(Bry_.new_u8("Q1"));
|
||||||
Gftest.Eq__str("Q2", String_.new_u8(actl.Qid()));
|
Gftest.Eq__str("Q2", String_.new_u8(actl.Qid()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
|||||||
*/
|
*/
|
||||||
package gplx.xowa.xtns.wbases.claims; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.wbases.*;
|
package gplx.xowa.xtns.wbases.claims; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.wbases.*;
|
||||||
import gplx.core.primitives.*;
|
import gplx.core.primitives.*;
|
||||||
import gplx.xowa.xtns.wbases.claims.itms.*;
|
import gplx.xowa.xtns.wbases.claims.enums.*; import gplx.xowa.xtns.wbases.claims.itms.*;
|
||||||
public class Wbase_claim_grp {
|
public class Wbase_claim_grp {
|
||||||
public Wbase_claim_grp(Int_obj_ref id_ref, Wbase_claim_base[] itms) {this.id_ref = id_ref; this.itms = itms;}
|
public Wbase_claim_grp(Int_obj_ref id_ref, Wbase_claim_base[] itms) {this.id_ref = id_ref; this.itms = itms;}
|
||||||
public Int_obj_ref Id_ref() {return id_ref;} private final Int_obj_ref id_ref;
|
public Int_obj_ref Id_ref() {return id_ref;} private final Int_obj_ref id_ref;
|
||||||
@ -23,6 +23,36 @@ public class Wbase_claim_grp {
|
|||||||
public String Id_str() {if (id_str == null) id_str = "P" + Int_.To_str(id_ref.Val()); return id_str;} private String id_str;
|
public String Id_str() {if (id_str == null) id_str = "P" + Int_.To_str(id_ref.Val()); return id_str;} private String id_str;
|
||||||
public int Len() {return itms.length;} private Wbase_claim_base[] itms;
|
public int Len() {return itms.length;} private Wbase_claim_base[] itms;
|
||||||
public Wbase_claim_base Get_at(int i) {return itms[i];}
|
public Wbase_claim_base Get_at(int i) {return itms[i];}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns the so called "best statements".
|
||||||
|
If there are preferred statements, then this is all the preferred statements.
|
||||||
|
If there are no preferred statements, then this is all normal statements.
|
||||||
|
*/
|
||||||
|
public Wbase_claim_base[] Get_best(List_adp tmp_snak_list) {
|
||||||
|
int len = itms.length;
|
||||||
|
boolean preferred_found = false;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
Wbase_claim_base itm = itms[i];
|
||||||
|
switch (itm.Rank_tid()) {
|
||||||
|
case Wbase_claim_rank_.Tid__preferred:
|
||||||
|
if (!preferred_found) {
|
||||||
|
if (tmp_snak_list.Len() > 0)
|
||||||
|
tmp_snak_list.Clear();
|
||||||
|
preferred_found = true;
|
||||||
|
}
|
||||||
|
tmp_snak_list.Add(itm);
|
||||||
|
break;
|
||||||
|
case Wbase_claim_rank_.Tid__normal:
|
||||||
|
if (!preferred_found)
|
||||||
|
tmp_snak_list.Add(itm);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tmp_snak_list.Count() == 0 ? Empty_array : (Wbase_claim_base[])tmp_snak_list.To_ary_and_clear(Wbase_claim_base.class);
|
||||||
|
}
|
||||||
|
private static final Wbase_claim_base[] Empty_array = new Wbase_claim_base[0];
|
||||||
|
|
||||||
public static List_adp Xto_list(Ordered_hash hash) {
|
public static List_adp Xto_list(Ordered_hash hash) {
|
||||||
int len = hash.Count();
|
int len = hash.Count();
|
||||||
List_adp rv = List_adp_.New();
|
List_adp rv = List_adp_.New();
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 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.claims; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.wbases.*;
|
||||||
|
import org.junit.*; import gplx.core.tests.*; import gplx.core.primitives.*;
|
||||||
|
import gplx.xowa.xtns.wbases.claims.enums.*; import gplx.xowa.xtns.wbases.claims.itms.*;
|
||||||
|
public class Wbase_claim_grp_tst {
|
||||||
|
@Test public void Get_best__preferred() {
|
||||||
|
Wbase_claim_grp_bldr bldr = new Wbase_claim_grp_bldr(123);
|
||||||
|
bldr.Add("P1", Wbase_claim_rank_.Tid__preferred);
|
||||||
|
bldr.Add("N1", Wbase_claim_rank_.Tid__normal);
|
||||||
|
bldr.Add("P2", Wbase_claim_rank_.Tid__preferred);
|
||||||
|
bldr.Add("N2", Wbase_claim_rank_.Tid__normal);
|
||||||
|
bldr.Test__Get_best("P1", "P2");
|
||||||
|
}
|
||||||
|
@Test public void Get_best__normal_if_no_preferred() {
|
||||||
|
Wbase_claim_grp_bldr bldr = new Wbase_claim_grp_bldr(123);
|
||||||
|
bldr.Add("D1", Wbase_claim_rank_.Tid__deprecated);
|
||||||
|
bldr.Add("D2", Wbase_claim_rank_.Tid__deprecated);
|
||||||
|
bldr.Add("N1", Wbase_claim_rank_.Tid__normal);
|
||||||
|
bldr.Add("N2", Wbase_claim_rank_.Tid__normal);
|
||||||
|
bldr.Test__Get_best("N1", "N2");
|
||||||
|
}
|
||||||
|
@Test public void Get_best__preferred_after_normal() {
|
||||||
|
Wbase_claim_grp_bldr bldr = new Wbase_claim_grp_bldr(123);
|
||||||
|
bldr.Add("N1", Wbase_claim_rank_.Tid__normal);
|
||||||
|
bldr.Add("N2", Wbase_claim_rank_.Tid__normal);
|
||||||
|
bldr.Add("P1", Wbase_claim_rank_.Tid__preferred);
|
||||||
|
bldr.Add("P2", Wbase_claim_rank_.Tid__preferred);
|
||||||
|
bldr.Test__Get_best("P1", "P2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Wbase_claim_grp_bldr {
|
||||||
|
private final int pid;
|
||||||
|
private final List_adp list = List_adp_.New();
|
||||||
|
public Wbase_claim_grp_bldr(int pid) {
|
||||||
|
this.pid = pid;
|
||||||
|
}
|
||||||
|
public void Add(String val, byte rank_tid) {
|
||||||
|
Wbase_claim_string claim = new Wbase_claim_string(pid, Wbase_claim_value_type_.Tid__value, Bry_.new_u8(val));
|
||||||
|
claim.Rank_tid_(rank_tid);
|
||||||
|
list.Add(claim);
|
||||||
|
}
|
||||||
|
public void Test__Get_best(String... expd) {
|
||||||
|
Wbase_claim_grp grp = new Wbase_claim_grp(Int_obj_ref.New(pid), (Wbase_claim_base[])list.To_ary_and_clear(Wbase_claim_base.class));
|
||||||
|
|
||||||
|
List_adp tmp_list = List_adp_.New();
|
||||||
|
Gftest.Eq__ary(expd, To_string(grp.Get_best(tmp_list)));
|
||||||
|
}
|
||||||
|
private String[] To_string(Wbase_claim_base[] items) {
|
||||||
|
int len = items.length;
|
||||||
|
String[] rv = new String[len];
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
Wbase_claim_string claim = (Wbase_claim_string)items[i];
|
||||||
|
rv[i] = String_.new_u8(claim.Val_bry());
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user