uca category support and other changes

v3.3.4
gnosygnu 8 years ago
parent e3b393650d
commit 3fc2e0741f

@ -5,5 +5,6 @@
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="lib" path="lib/commons-compress-1.5.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="lib/xz-1.5.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

@ -49,6 +49,12 @@ public class Hex_utl_ {
}
return rv;
}
public static byte[] Encode_bry(byte[] src) {
int src_len = src.length;
byte[] trg = new byte[src_len * 2];
Encode_bry(src, trg);
return trg;
}
public static void Encode_bry(byte[] src, byte[] trg) {
int src_len = src.length, trg_len = trg.length;
if (trg_len != src_len * 2) throw Err_.new_("hex", "trg.len must be src.len * 2", "src_len", src_len, "trg_len", trg_len);
@ -59,6 +65,14 @@ public class Hex_utl_ {
trg[++trg_idx] = To_byte_lcase(0xf & src_byte);
}
}
public static void Encode_bfr(Bry_bfr bfr, byte[] src) {
int src_len = src.length;
for (int src_idx = 0; src_idx < src_len; ++src_idx) {
byte src_byte = src[src_idx];
bfr.Add_byte(To_byte_lcase(0xf & src_byte >>> 4));
bfr.Add_byte(To_byte_lcase(0xf & src_byte));
}
}
public static String To_str(int val, int pad) {
char[] ary = new char[8]; int idx = 8; // 8 is max len of hexString; (2^4 * 8); EX: int.MaxValue = 7FFFFFFF
do {

@ -190,7 +190,7 @@ public class IoEngine_memory extends IoEngine_base {
return Io_stream_rdr_.Noop;
}
byte[] bry = Bry_.new_u8(FetchFil(Io_url_.mem_fil_(xrg.Src())).Text());
return Io_stream_rdr_.mem_(bry);
return Io_stream_rdr_.New__mem(bry);
}
IoItmHash dirs = IoItmHash.new_();

@ -638,7 +638,7 @@ class Io_stream_rdr_http implements Io_stream_rdr {
public Io_stream_rdr_http(IoEngine_xrg_downloadFil xrg) {
this.xrg = xrg;
} private IoEngine_xrg_downloadFil xrg;
public byte Tid() {return Io_stream_.Tid_raw;}
public byte Tid() {return Io_stream_tid_.Tid__raw;}
public boolean Exists() {return exists;} private boolean exists = false;
public Io_url Url() {return url;} public Io_stream_rdr Url_(Io_url v) {url = v; return this;} private Io_url url;
public long Len() {return len;} public Io_stream_rdr Len_(long v) {len = v; return this;} private long len = IoItmFil.Size_invalid; // NOTE: must default size to -1; DATE:2014-06-21

@ -1,55 +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.core.ios.streams; import gplx.*; import gplx.core.*; import gplx.core.ios.*;
public class Io_stream_ { // SERIALIZED
public static final byte Tid_null = 0, Tid_raw = 1, Tid_zip = 2, Tid_gzip = 3, Tid_bzip2 = 4;
public static final String Ext_zip = ".zip", Ext_gz = ".gz", Ext_bz2 = ".bz2";
public static String Obsolete_to_str(byte v) {
switch (v) {
case Io_stream_.Tid_raw : return ".xdat";
case Io_stream_.Tid_zip : return ".zip";
case Io_stream_.Tid_gzip : return ".gz";
case Io_stream_.Tid_bzip2 : return ".bz2";
default : throw Err_.new_unhandled(v);
}
}
public static byte Obsolete_to_tid(String v) {
if (String_.Eq(v, ".xdat")) return Io_stream_.Tid_raw;
else if (String_.Eq(v, ".zip")) return Io_stream_.Tid_zip;
else if (String_.Eq(v, ".gz")) return Io_stream_.Tid_gzip;
else if (String_.Eq(v, ".bz2")) return Io_stream_.Tid_bzip2;
else throw Err_.new_unhandled(v);
}
public static String To_str(byte v) {
switch (v) {
case Io_stream_.Tid_raw : return "raw";
case Io_stream_.Tid_zip : return "zip";
case Io_stream_.Tid_gzip : return "gzip";
case Io_stream_.Tid_bzip2 : return "bzip2";
default : throw Err_.new_unhandled(v);
}
}
public static byte To_tid(String v) {
if (String_.Eq(v, "raw")) return Io_stream_.Tid_raw;
else if (String_.Eq(v, "zip")) return Io_stream_.Tid_zip;
else if (String_.Eq(v, "gzip")) return Io_stream_.Tid_gzip;
else if (String_.Eq(v, "bzip2")) return Io_stream_.Tid_bzip2;
else throw Err_.new_unhandled(v);
}
}

@ -17,14 +17,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.core.ios.streams; import gplx.*; import gplx.core.*; import gplx.core.ios.*;
public interface Io_stream_rdr extends Rls_able {
byte Tid();
boolean Exists();
Io_url Url(); Io_stream_rdr Url_(Io_url v);
long Len(); Io_stream_rdr Len_(long v);
Io_stream_rdr Open();
void Open_mem(byte[] v);
Object Under();
byte Tid();
boolean Exists();
Io_url Url(); Io_stream_rdr Url_(Io_url v);
long Len(); Io_stream_rdr Len_(long v);
Io_stream_rdr Open();
void Open_mem(byte[] v);
Object Under();
int Read(byte[] bry, int bgn, int len);
long Skip(long len);
int Read(byte[] bry, int bgn, int len);
long Skip(long len);
}

@ -16,39 +16,43 @@ 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.core.ios.streams; import gplx.*; import gplx.core.*; import gplx.core.ios.*;
import gplx.core.ios.streams.rdrs.*;
public class Io_stream_rdr_ {
public static Io_stream_rdr file_(Io_url url) {return new Io_stream_rdr_file().Url_(url);}
public static Io_stream_rdr file_(java.io.InputStream strm) {return new Io_stream_rdr_file().Under_(strm);}
public static Io_stream_rdr zip_(Io_url url) {return new Io_stream_rdr_zip().Url_(url);}
public static Io_stream_rdr gzip_(Io_url url) {return new Io_stream_rdr_gzip().Url_(url);}
public static Io_stream_rdr bzip2_(Io_url url) {return new Io_stream_rdr_bzip2().Url_(url);}
public static Io_stream_rdr new_by_url_(Io_url url) {
public static final int Read_done = -1, Read_done_compare = 1;
public static final Io_stream_rdr Noop = new Io_stream_rdr__noop();
public static Io_stream_rdr New__raw(Io_url url) {return new Io_stream_rdr__raw().Url_(url);}
public static Io_stream_rdr New__raw(java.io.InputStream strm) {return new Io_stream_rdr__raw().Under_(strm);}
private static Io_stream_rdr New__zip(Io_url url) {return new Io_stream_rdr__zip().Url_(url);}
private static Io_stream_rdr New__gzip(Io_url url) {return new Io_stream_rdr__gzip().Url_(url);}
public static Io_stream_rdr New__bzip2(Io_url url) {return new Io_stream_rdr__bzip2().Url_(url);}
public static Io_stream_rdr New__mem(String v) {return New__mem(Bry_.new_u8(v));}
public static Io_stream_rdr New__mem(byte[] v) {
Io_stream_rdr rv = new Io_stream_rdr__adp(New__mem_as_stream(v));
rv.Len_(v.length);
return rv;
}
public static java.io.InputStream New__mem_as_stream(byte[] v) {
return new java.io.ByteArrayInputStream(v);
}
public static Io_stream_rdr New_by_url(Io_url url) {
String ext = url.Ext();
if (String_.Eq(ext, Io_stream_.Ext_zip)) return gplx.core.ios.streams.Io_stream_rdr_.zip_(url);
else if (String_.Eq(ext, Io_stream_.Ext_gz)) return gplx.core.ios.streams.Io_stream_rdr_.gzip_(url);
else if (String_.Eq(ext, Io_stream_.Ext_bz2)) return gplx.core.ios.streams.Io_stream_rdr_.bzip2_(url);
else return gplx.core.ios.streams.Io_stream_rdr_.file_(url);
if (String_.Eq(ext, Io_stream_tid_.Ext__zip)) return Io_stream_rdr_.New__zip(url);
else if (String_.Eq(ext, Io_stream_tid_.Ext__gz)) return Io_stream_rdr_.New__gzip(url);
else if (String_.Eq(ext, Io_stream_tid_.Ext__bz2)) return Io_stream_rdr_.New__bzip2(url);
else if (String_.Eq(ext, Io_stream_tid_.Ext__xz)) return new Io_stream_rdr__xz().Url_(url);
else return Io_stream_rdr_.New__raw(url);
}
public static Io_stream_rdr new_by_tid_(byte tid) {
public static Io_stream_rdr New_by_tid(byte tid) {
switch (tid) {
case Io_stream_.Tid_raw: return new Io_stream_rdr_file();
case Io_stream_.Tid_zip: return new Io_stream_rdr_zip();
case Io_stream_.Tid_gzip: return new Io_stream_rdr_gzip();
case Io_stream_.Tid_bzip2: return new Io_stream_rdr_bzip2();
default: throw Err_.new_unhandled(tid);
}
}
public static byte[] Load_all(Io_url url) {
Io_stream_rdr rdr = new_by_url_(url);
Bry_bfr rv = Bry_bfr_.New();
try {
rdr.Open();
return Load_all_as_bry(rv, rdr);
case Io_stream_tid_.Tid__raw: return new Io_stream_rdr__raw();
case Io_stream_tid_.Tid__zip: return new Io_stream_rdr__zip();
case Io_stream_tid_.Tid__gzip: return new Io_stream_rdr__gzip();
case Io_stream_tid_.Tid__bzip2: return new Io_stream_rdr__bzip2();
case Io_stream_tid_.Tid__xz: return new Io_stream_rdr__xz();
default: throw Err_.new_unhandled_default(tid);
}
finally {rdr.Rls();}
}
public static String Load_all_as_str(Io_stream_rdr rdr) {return String_.new_u8(Load_all_as_bry(rdr));}
public static byte[] Load_all_as_bry(Io_stream_rdr rdr) {return Load_all_as_bry(Bry_bfr_.New(), rdr);}
public static String Load_all_as_str(Io_stream_rdr rdr) {return String_.new_u8(Load_all_as_bry(Bry_bfr_.New(), rdr));}
public static byte[] Load_all_as_bry(Bry_bfr rv, Io_stream_rdr rdr) {
Load_all_to_bfr(rv, rdr);
return rv.To_bry_and_clear();
@ -63,24 +67,7 @@ public class Io_stream_rdr_ {
}
} finally {rdr.Rls();}
}
public static final Io_stream_rdr Noop = new Io_stream_rdr_noop();
public static Io_stream_rdr mem_(String v) {return mem_(Bry_.new_u8(v));}
public static Io_stream_rdr mem_(byte[] v) {
Io_stream_rdr rv = new Io_stream_rdr_adp(Stream_new_mem(v));
rv.Len_(v.length);
return rv;
}
public static java.io.InputStream Stream_new_mem(byte[] v) {
return new java.io.ByteArrayInputStream(v);
}
public static boolean Stream_close(java.io.InputStream stream) {
try {
if (stream != null)
stream.close();
return true;
} catch (Exception e) {Err_.Noop(e); return false;}
}
public static int Stream_read_by_parts(java.io.InputStream stream, int part_len, byte[] bry, int bgn, int len) {
public static int Read_by_parts(java.io.InputStream stream, int part_len, byte[] bry, int bgn, int len) {
/*
NOTE: BZip2CompressorInputStream will fail if large len is used
Instead, make smaller requests and fill bry
@ -106,163 +93,10 @@ public class Io_stream_rdr_ {
throw Err_.new_exc(exc, "io", "read failed", "bgn", bgn, "len", len);
}
}
public static final int Read_done = -1;
public static final int Read_done_compare = 1;
}
class Io_stream_rdr_noop implements Io_stream_rdr {
public Object Under() {return null;}
public byte Tid() {return Io_stream_.Tid_null;}
public boolean Exists() {return false;}
public Io_url Url() {return Io_url_.Empty;} public Io_stream_rdr Url_(Io_url v) {return this;}
public long Len() {return Io_mgr.Len_null;} public Io_stream_rdr Len_(long v) {return this;}
public void Open_mem(byte[] v) {}
public Io_stream_rdr Open() {return this;}
public int Read(byte[] bry, int bgn, int len) {return Io_stream_rdr_.Read_done;}
public long Skip(long len) {return Io_stream_rdr_.Read_done;}
public void Rls() {}
}
class Io_stream_rdr_adp implements Io_stream_rdr {
private java.io.InputStream strm;
public Io_stream_rdr_adp(java.io.InputStream strm) {this.strm = strm;}
public Object Under() {return strm;}
public byte Tid() {return Io_stream_.Tid_raw;}
public boolean Exists() {return len > 0;}
public Io_url Url() {return url;} public Io_stream_rdr Url_(Io_url v) {this.url = v; return this;} private Io_url url;
public long Len() {return len;} public Io_stream_rdr Len_(long v) {len = v; return this;} private long len = Io_mgr.Len_null;
public void Open_mem(byte[] v) {}
public Io_stream_rdr Open() {return this;}
public int Read(byte[] bry, int bgn, int len) {
try {return strm.read(bry, bgn, len);}
catch (Exception e) {throw Err_.new_exc(e, "io", "read failed", "bgn", bgn, "len", len);}
}
public long Skip(long len) {
try {return strm.skip(len);}
catch (Exception e) {throw Err_.new_exc(e, "io", "skip failed", "len", len);}
}
public void Rls() {
try {strm.close();}
catch (Exception e) {throw Err_.new_exc(e, "io", "close failed", "url", url.Xto_api());}
}
}
abstract class Io_stream_rdr_base implements Io_stream_rdr {
public abstract byte Tid();
public boolean Exists() {return this.Len() > 0;}
public Object Under() {return stream;} public Io_stream_rdr Under_(java.io.InputStream v) {this.stream = v; return this;} protected java.io.InputStream stream;
public Io_url Url() {return url;} public Io_stream_rdr Url_(Io_url v) {this.url = v; return this;} protected Io_url url;
public long Len() {return len;} public Io_stream_rdr Len_(long v) {len = v; return this;} private long len = Io_mgr.Len_null;
public void Open_mem(byte[] v) {
stream = Wrap_stream(new java.io.ByteArrayInputStream(v));
}
public Io_stream_rdr Open() {
try {stream = Wrap_stream(new java.io.FileInputStream(url.Xto_api()));}
catch (Exception e) {throw Err_.new_exc(e, "io", "open failed", "url", url.Xto_api());}
return this;
}
public int Read(byte[] bry, int bgn, int len) {
try {return stream.read(bry, bgn, len);}
catch (Exception e) {throw Err_.new_exc(e, "io", "read failed", "bgn", bgn, "len", len);}
}
public long Skip(long len) {
try {return stream.skip(len);}
catch (Exception e) {throw Err_.new_exc(e, "io", "skip failed", "len", len);}
}
public void Rls() {
try {stream.close();}
catch (Exception e) {throw Err_.new_exc(e, "io", "close failed", "url", url.Xto_api());}
}
public abstract java.io.InputStream Wrap_stream(java.io.InputStream stream);
}
class Io_stream_rdr_file extends Io_stream_rdr_base {
@Override public byte Tid() {return Io_stream_.Tid_raw;}
public Io_stream_rdr Open() {
public static boolean Close(java.io.InputStream stream) {
try {
if (!Io_mgr.Instance.Exists(url))
stream = Wrap_stream(new java.io.ByteArrayInputStream(Bry_.Empty));
else {
if (url.Info().EngineKey() == IoEngine_.MemKey)
stream = Wrap_stream(new java.io.ByteArrayInputStream(Io_mgr.Instance.LoadFilBry(url.Xto_api())));
else
stream = Wrap_stream(new java.io.FileInputStream(url.Xto_api()));
}
}
catch (Exception e) {throw Err_.new_exc(e, "io", "open failed", "url", url.Xto_api());}
return this;
}
@Override public java.io.InputStream Wrap_stream(java.io.InputStream stream) {return stream;}
}
class Io_stream_rdr_zip implements Io_stream_rdr {
@Override public byte Tid() {return Io_stream_.Tid_zip;}
public boolean Exists() {return this.Len() > 0;}
public Io_url Url() {return url;} public Io_stream_rdr Url_(Io_url v) {this.url = v; return this;} Io_url url;
public long Len() {return len;} public Io_stream_rdr Len_(long v) {len = v; return this;} private long len = Io_mgr.Len_null;
public Object Under() {return zip_stream;} private java.util.zip.ZipInputStream zip_stream;
public void Src_bfr_(Bry_bfr v) {this.src_bfr = v;} Bry_bfr src_bfr;
public void Open_mem(byte[] v) {
Wrap_stream(new java.io.ByteArrayInputStream(v));
}
public Io_stream_rdr Open() {
try {Wrap_stream(new java.io.FileInputStream(url.Xto_api()));}
catch (Exception e) {throw Err_.new_exc(e, "io", "open failed", "url", url.Xto_api());}
return this;
}
void Wrap_stream(java.io.InputStream input_stream) {zip_stream = new java.util.zip.ZipInputStream(input_stream);}
public int Read(byte[] bry, int bgn, int len) {
try {
while (true){
int read = zip_stream.read(bry, bgn, len);
if (read == Io_stream_rdr_.Read_done) {
if (zip_stream.getNextEntry() == null)
return Io_stream_rdr_.Read_done;
}
else
return read;
}
}
catch (Exception e) {throw Err_.new_exc(e, "io", "read failed", "bgn", bgn, "len", len);}
}
public long Skip(long len) {
try {return zip_stream.skip(len);}
catch (Exception e) {throw Err_.new_exc(e, "io", "skip failed", "len", len);}
}
public void Rls() {
try {zip_stream.close();}
catch (Exception e) {throw Err_.new_exc(e, "io", "close failed", "url", url.Xto_api());}
}
}
class Io_stream_rdr_gzip extends Io_stream_rdr_base {
@Override public byte Tid() {return Io_stream_.Tid_gzip;}
@Override public int Read(byte[] bry, int bgn, int len) {
synchronized (this) {
try {
int total_read = 0;
while (true) { // NOTE: the gz stream reads partially; (request 100; only get back 10); keep reading until entire bfr is full or -1
int read = stream.read(bry, bgn, len);
if (read == Io_stream_rdr_.Read_done) break;
total_read += read;
if (total_read >= len) break; // entire bfr full; stop
bgn += read; // increase bgn by amount read
len -= read; // decrease len by amount read
}
return total_read == 0 ? Io_stream_rdr_.Read_done : total_read; // gzip seems to allow 0 bytes read (bz2 and zip return -1 instead); normalize return to -1;
}
catch (Exception e) {
throw Err_.new_exc(e, "io", "read failed", "bgn", bgn, "len", len);
}
}
}
@Override public java.io.InputStream Wrap_stream(java.io.InputStream stream) {
try {return new java.util.zip.GZIPInputStream(stream);}
catch (Exception exc) {throw Err_.new_wo_type("failed to open gz stream");}
}
}
class Io_stream_rdr_bzip2 extends Io_stream_rdr_base {
@Override public byte Tid() {return Io_stream_.Tid_bzip2;}
@Override public java.io.InputStream Wrap_stream(java.io.InputStream stream) {
try {return new org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream(stream, true);}
catch (Exception exc) {throw Err_.new_wo_type("failed to open bzip2 stream");}
}
@Override public int Read(byte[] bry, int bgn, int len) {
return Io_stream_rdr_.Stream_read_by_parts(stream, Read_len, bry, bgn, len);
if (stream != null) stream.close();
return true;
} catch (Exception e) {Err_.Noop(e); return false;}
}
private static final int Read_len = Io_mgr.Len_mb * 128;
}

@ -17,8 +17,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.core.ios.streams; import gplx.*; import gplx.core.*; import gplx.core.ios.*;
import org.junit.*;
public class Io_stream_rdr_tst {
@Before public void init() {fxt.Clear();} private Io_stream_rdr_fxt fxt = new Io_stream_rdr_fxt();
public class Io_stream_rdr__tst {
@Before public void init() {fxt.Clear();} private Io_stream_rdr__fxt fxt = new Io_stream_rdr__fxt();
@After public void term() {fxt.Rls();}
@Test public void Bz2_read() {
fxt .Init_stream("abcd") // read everything at once
@ -30,27 +30,27 @@ public class Io_stream_rdr_tst {
;
}
}
class Io_stream_rdr_fxt {
class Io_stream_rdr__fxt {
private java.io.InputStream stream;
private int stream_bry_len;
public void Clear() {
expd_bytes_read = Int_.Min_value;
}
public Io_stream_rdr_fxt Expd_bytes_read(int v) {expd_bytes_read = v; return this;} private int expd_bytes_read = Int_.Min_value;
public Io_stream_rdr_fxt Init_stream(String v) {
public Io_stream_rdr__fxt Expd_bytes_read(int v) {expd_bytes_read = v; return this;} private int expd_bytes_read = Int_.Min_value;
public Io_stream_rdr__fxt Init_stream(String v) {
byte[] stream_bry = Bry_.new_a7(v);
stream_bry_len = stream_bry.length;
stream = Io_stream_rdr_.Stream_new_mem(stream_bry);
stream = Io_stream_rdr_.New__mem_as_stream(stream_bry);
return this;
}
public Io_stream_rdr_fxt Test_read(int bgn, int len, String expd_str) {
public Io_stream_rdr__fxt Test_read(int bgn, int len, String expd_str) {
byte[] bfr = new byte[stream_bry_len]; // allocate whole stream; may not use it all
int actl_bytes_read = Io_stream_rdr_.Stream_read_by_parts(stream, 8, bfr, bgn, len);
int actl_bytes_read = Io_stream_rdr_.Read_by_parts(stream, 8, bfr, bgn, len);
Tfds.Eq(expd_bytes_read, actl_bytes_read, "bytes_read");
Tfds.Eq(expd_str, String_.new_u8(bfr, bgn, bgn + actl_bytes_read), "str");
return this;
}
public void Rls() {
Io_stream_rdr_.Stream_close(stream);
Io_stream_rdr_.Close(stream);
}
}

@ -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.core.ios.streams; import gplx.*; import gplx.core.*; import gplx.core.ios.*;
public class Io_stream_tid_ {
public static final byte Tid__null = 0, Tid__raw = 1, Tid__zip = 2, Tid__gzip = 3, Tid__bzip2 = 4, Tid__xz = 5; // SERIALIZED:xo.text_db;xo.html_db
public static final String Ext__zip = ".zip", Ext__gz = ".gz", Ext__bz2 = ".bz2", Ext__xz = ".xz";
private static final String Key__raw = "raw", Key__zip = "zip", Key__gzip = "gzip", Key__bzip2 = "bzip2", Key__xz = "xz";
public static String To_key(byte v) {
switch (v) {
case Io_stream_tid_.Tid__raw : return Key__raw;
case Io_stream_tid_.Tid__zip : return Key__zip;
case Io_stream_tid_.Tid__gzip : return Key__gzip;
case Io_stream_tid_.Tid__bzip2 : return Key__bzip2;
case Io_stream_tid_.Tid__xz : return Key__xz;
default : throw Err_.new_unhandled_default(v);
}
}
public static byte To_tid(String v) {
if (String_.Eq(v, Key__raw)) return Io_stream_tid_.Tid__raw;
else if (String_.Eq(v, Key__zip)) return Io_stream_tid_.Tid__zip;
else if (String_.Eq(v, Key__gzip)) return Io_stream_tid_.Tid__gzip;
else if (String_.Eq(v, Key__bzip2)) return Io_stream_tid_.Tid__bzip2;
else if (String_.Eq(v, Key__xz)) return Io_stream_tid_.Tid__xz;
else throw Err_.new_unhandled_default(v);
}
public static String Obsolete_to_str(byte v) {
switch (v) {
case Io_stream_tid_.Tid__raw : return ".xdat";
case Io_stream_tid_.Tid__zip : return ".zip";
case Io_stream_tid_.Tid__gzip : return ".gz";
case Io_stream_tid_.Tid__bzip2 : return ".bz2";
default : throw Err_.new_unhandled_default(v);
}
}
public static byte Obsolete_to_tid(String v) {
if (String_.Eq(v, ".xdat")) return Io_stream_tid_.Tid__raw;
else if (String_.Eq(v, ".zip")) return Io_stream_tid_.Tid__zip;
else if (String_.Eq(v, ".gz")) return Io_stream_tid_.Tid__gzip;
else if (String_.Eq(v, ".bz2")) return Io_stream_tid_.Tid__bzip2;
else throw Err_.new_unhandled_default(v);
}
}

@ -17,12 +17,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.core.ios.streams; import gplx.*; import gplx.core.*; import gplx.core.ios.*;
public interface Io_stream_wtr extends Rls_able {
byte Tid();
Io_url Url(); Io_stream_wtr Url_(Io_url v);
void Trg_bfr_(Bry_bfr v);
Io_stream_wtr Open();
byte[] To_ary_and_clear();
byte Tid();
Io_url Url(); Io_stream_wtr Url_(Io_url v);
void Trg_bfr_(Bry_bfr v);
Io_stream_wtr Open();
byte[] To_ary_and_clear();
void Write(byte[] bry, int bgn, int len);
void Flush();
void Write(byte[] bry, int bgn, int len);
void Flush();
}

@ -16,44 +16,38 @@ 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.core.ios.streams; import gplx.*; import gplx.core.*; import gplx.core.ios.*;
import gplx.core.ios.streams.wtrs.*;
public class Io_stream_wtr_ {
public static Io_stream_wtr bzip2_(Io_url url) {return new Io_stream_wtr_bzip2().Url_(url);}
public static Io_stream_wtr gzip_(Io_url url) {return new Io_stream_wtr_gzip().Url_(url);}
public static Io_stream_wtr zip_(Io_url url) {return new Io_stream_wtr_zip().Url_(url);}
public static Io_stream_wtr file_(Io_url url) {return new Io_stream_wtr_file().Url_(url);}
public static Io_stream_wtr new_by_url_(Io_url url) {
public static Io_stream_wtr New__raw(Io_url url) {return new Io_stream_wtr__raw().Url_(url);}
private static Io_stream_wtr New__zip(Io_url url) {return new Io_stream_wtr__zip().Url_(url);}
private static Io_stream_wtr New__gzip(Io_url url) {return new Io_stream_wtr__gzip().Url_(url);}
private static Io_stream_wtr New__bzip2(Io_url url) {return new Io_stream_wtr__bzip2().Url_(url);}
public static Io_stream_wtr New_by_url(Io_url url) {
String ext = url.Ext();
if (String_.Eq(ext, Io_stream_.Ext_zip)) return gplx.core.ios.streams.Io_stream_wtr_.zip_(url);
else if (String_.Eq(ext, Io_stream_.Ext_gz)) return gplx.core.ios.streams.Io_stream_wtr_.gzip_(url);
else if (String_.Eq(ext, Io_stream_.Ext_bz2)) return gplx.core.ios.streams.Io_stream_wtr_.bzip2_(url);
else return gplx.core.ios.streams.Io_stream_wtr_.file_(url);
if (String_.Eq(ext, Io_stream_tid_.Ext__zip)) return Io_stream_wtr_.New__zip(url);
else if (String_.Eq(ext, Io_stream_tid_.Ext__gz)) return Io_stream_wtr_.New__gzip(url);
else if (String_.Eq(ext, Io_stream_tid_.Ext__bz2)) return Io_stream_wtr_.New__bzip2(url);
else if (String_.Eq(ext, Io_stream_tid_.Ext__xz)) return new Io_stream_wtr__xz().Url_(url);
else return Io_stream_wtr_.New__raw(url);
}
public static Io_stream_wtr new_by_mem(Bry_bfr bfr, byte tid) {
Io_stream_wtr wtr = new_by_tid_(tid).Url_(Io_url_.Empty);
wtr.Trg_bfr_(bfr);
return wtr;
}
public static Io_stream_wtr new_by_tid_(byte v) {
public static Io_stream_wtr New_by_tid(byte v) {
switch (v) {
case gplx.core.ios.streams.Io_stream_.Tid_raw : return new Io_stream_wtr_file();
case gplx.core.ios.streams.Io_stream_.Tid_zip : return new Io_stream_wtr_zip();
case gplx.core.ios.streams.Io_stream_.Tid_gzip : return new Io_stream_wtr_gzip();
case gplx.core.ios.streams.Io_stream_.Tid_bzip2 : return new Io_stream_wtr_bzip2();
default : throw Err_.new_unhandled(v);
case Io_stream_tid_.Tid__raw: return new Io_stream_wtr__raw();
case Io_stream_tid_.Tid__zip: return new Io_stream_wtr__zip();
case Io_stream_tid_.Tid__gzip: return new Io_stream_wtr__gzip();
case Io_stream_tid_.Tid__bzip2: return new Io_stream_wtr__bzip2();
case Io_stream_tid_.Tid__xz: return new Io_stream_wtr__xz();
default: throw Err_.new_unhandled(v);
}
}
public static void Save_all(Io_url url, byte[] bry, int bgn, int end) {
Io_stream_wtr wtr = new_by_url_(url);
try {
wtr.Open();
wtr.Write(bry, bgn, end);
wtr.Flush();
}
finally {wtr.Rls();}
public static Io_stream_wtr New_by_mem(Bry_bfr bfr, byte tid) {
Io_stream_wtr wtr = New_by_tid(tid).Url_(Io_url_.Empty);
wtr.Trg_bfr_(bfr);
return wtr;
}
public static void Save_rdr(Io_url url, Io_stream_rdr rdr, Io_download_fmt download_progress) {
byte[] bry = new byte[4096];
Io_stream_wtr wtr = new_by_url_(url);
Io_stream_wtr wtr = New_by_url(url);
try {
wtr.Open();
if (download_progress != Io_download_fmt.Null)
@ -72,142 +66,3 @@ public class Io_stream_wtr_ {
finally {wtr.Rls(); rdr.Rls();}
}
}
abstract class Io_stream_wtr_base implements Io_stream_wtr {
java.io.OutputStream zip_stream;
public Io_url Url() {return url;} public Io_stream_wtr Url_(Io_url v) {url = v; trg_bfr = null; return this;} Io_url url;
public void Trg_bfr_(Bry_bfr v) {trg_bfr = v;} Bry_bfr trg_bfr; java.io.ByteArrayOutputStream mem_stream;
public byte[] To_ary_and_clear() {return trg_bfr.To_bry_and_clear();}
public Io_stream_wtr Open() {
java.io.OutputStream bry_stream = null;
if (trg_bfr == null) {
if (!Io_mgr.Instance.ExistsFil(url)) Io_mgr.Instance.SaveFilStr(url, "");
try {bry_stream = new java.io.FileOutputStream(url.Raw());}
catch (Exception e) {throw Err_.new_exc(e, "io", "open failed", "url", url.Raw());}
}
else {
mem_stream = new java.io.ByteArrayOutputStream();
bry_stream = mem_stream;
}
zip_stream = Wrap_stream(bry_stream);
return this;
}
public void Write(byte[] bry, int bgn, int len) {
try {zip_stream.write(bry, bgn, len);}
catch (Exception e) {Err_.new_exc(e, "io", "write failed", "bgn", bgn, "len", len);}
}
public void Flush() {
if (trg_bfr != null) {
try {zip_stream.close();} catch (Exception e) {throw Err_.new_exc(e, "io", "flush failed");} // must close zip_stream to flush all bytes
trg_bfr.Add(mem_stream.toByteArray());
}
}
public void Rls() {
try {
if (zip_stream != null) zip_stream.close();
if (mem_stream != null) mem_stream.close();
}
catch (Exception e) {throw Err_.new_exc(e, "io", "close failed", "url", url.Raw());}
}
public abstract java.io.OutputStream Wrap_stream(java.io.OutputStream stream);
}
class Io_stream_wtr_bzip2 extends Io_stream_wtr_base {
@Override public byte Tid() {return Io_stream_.Tid_bzip2;}
@Override public java.io.OutputStream Wrap_stream(java.io.OutputStream stream) {
try {return new org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream(stream);}
catch (Exception e) {throw Err_.new_exc(e, "io", "failed to open bzip2 stream");}
}
static final byte[] Bz2_header = new byte[] {Byte_ascii.Ltr_B, Byte_ascii.Ltr_Z};
}
class Io_stream_wtr_gzip extends Io_stream_wtr_base {
@Override public byte Tid() {return Io_stream_.Tid_gzip;}
@Override public java.io.OutputStream Wrap_stream(java.io.OutputStream stream) {
try {return new java.util.zip.GZIPOutputStream(stream);}
catch (Exception e) {throw Err_.new_exc(e, "io", "failed to open gz stream");}
}
}
class Io_stream_wtr_zip implements Io_stream_wtr {
private java.util.zip.ZipOutputStream zip_stream;
@Override public byte Tid() {return Io_stream_.Tid_zip;}
public Io_url Url() {return url;} public Io_stream_wtr Url_(Io_url v) {url = v; trg_bfr = null; return this;} private Io_url url = Io_url_.Empty;
public void Trg_bfr_(Bry_bfr v) {trg_bfr = v;} private Bry_bfr trg_bfr; private java.io.ByteArrayOutputStream mem_stream;
// rely on zip_stream to close bry_stream
public Io_stream_wtr Open() {
java.io.OutputStream bry_stream;
if (trg_bfr == null) {
if (!Io_mgr.Instance.ExistsFil(url)) Io_mgr.Instance.SaveFilStr(url, ""); // create file if it doesn't exist
try {bry_stream = new java.io.FileOutputStream(url.Xto_api());}
catch (Exception e) {throw Err_.new_exc(e, "io", "open failed", "url", url.Raw());}
}
else {
mem_stream = new java.io.ByteArrayOutputStream();
bry_stream = mem_stream;
}
zip_stream = new java.util.zip.ZipOutputStream(bry_stream);
java.util.zip.ZipEntry entry = new java.util.zip.ZipEntry("file");
try {zip_stream.putNextEntry(entry);}
catch (Exception e) {throw Err_.new_exc(e, "io", "open failed", "url", url.Raw());}
return this;
}
public void Write(byte[] bry, int bgn, int len) {
try {zip_stream.write(bry, bgn, len);}
catch (Exception e) {throw Err_.new_exc(e, "io", "write failed", "url", url.Raw(), "bgn", bgn, "len", len);}
}
public void Flush() {// fixed as of DATE:2014-04-15
try {
zip_stream.closeEntry();
zip_stream.close();
if (trg_bfr != null)
trg_bfr.Add(mem_stream.toByteArray());
zip_stream.flush();
}
catch (Exception e) {throw Err_.new_exc(e, "io", "flush failed", "url", url.Raw());}
}
public void Rls() {
try {
if (zip_stream != null) zip_stream.close();
if (mem_stream != null) mem_stream.close();
}
catch (Exception e) {throw Err_.new_exc(e, "io", "close failed", "url", url.Raw());}
}
public byte[] To_ary_and_clear() {
byte[] rv = trg_bfr.To_bry_and_clear();
this.Rls();
return rv;
}
}
class Io_stream_wtr_file implements Io_stream_wtr {
IoStream bry_stream;
@Override public byte Tid() {return Io_stream_.Tid_raw;}
public Io_url Url() {return url;} public Io_stream_wtr Url_(Io_url v) {url = v; return this;} Io_url url;
public void Trg_bfr_(Bry_bfr v) {trg_bfr = v;} private Bry_bfr trg_bfr; java.io.ByteArrayOutputStream mem_stream;
public Io_stream_wtr Open() {
try {
if (trg_bfr == null)
bry_stream = Io_mgr.Instance.OpenStreamWrite(url);
}
catch (Exception e) {throw Err_.new_exc(e, "io", "open failed", "url", url.Raw());}
return this;
}
public void Write(byte[] bry, int bgn, int len) {
if (trg_bfr == null) {
try {bry_stream.Write(bry, bgn, len);}
catch (Exception e) {throw Err_.new_exc(e, "io", "write failed", "url", url.Raw(), "bgn", bgn, "len", len);}
}
else
trg_bfr.Add_mid(bry, bgn, bgn + len);
}
public byte[] To_ary_and_clear() {
return trg_bfr == null ? Io_mgr.Instance.LoadFilBry(url) : trg_bfr.To_bry_and_clear();
}
public void Flush() {
if (trg_bfr == null)
bry_stream.Flush();
}
public void Rls() {
try {
if (trg_bfr == null)
bry_stream.Rls();
}
catch (Exception e) {throw Err_.new_exc(e, "io", "close failed", "url", url.Raw());}
}
}

@ -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.core.ios.streams.rdrs; import gplx.*; import gplx.core.*; import gplx.core.ios.*; import gplx.core.ios.streams.*;
public class Io_stream_rdr__adp implements Io_stream_rdr {
private java.io.InputStream strm;
public Io_stream_rdr__adp(java.io.InputStream strm) {this.strm = strm;}
public Object Under() {return strm;}
public byte Tid() {return Io_stream_tid_.Tid__raw;}
public boolean Exists() {return len > 0;}
public Io_url Url() {return url;} public Io_stream_rdr Url_(Io_url v) {this.url = v; return this;} private Io_url url;
public long Len() {return len;} public Io_stream_rdr Len_(long v) {len = v; return this;} private long len = Io_mgr.Len_null;
public void Open_mem(byte[] v) {}
public Io_stream_rdr Open() {return this;}
public int Read(byte[] bry, int bgn, int len) {
try {return strm.read(bry, bgn, len);}
catch (Exception e) {throw Err_.new_exc(e, "io", "read failed", "bgn", bgn, "len", len);}
}
public long Skip(long len) {
try {return strm.skip(len);}
catch (Exception e) {throw Err_.new_exc(e, "io", "skip failed", "len", len);}
}
public void Rls() {
try {strm.close();}
catch (Exception e) {throw Err_.new_exc(e, "io", "close failed", "url", url.Xto_api());}
}
}

@ -0,0 +1,48 @@
/*
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.core.ios.streams.rdrs; import gplx.*; import gplx.core.*; import gplx.core.ios.*; import gplx.core.ios.streams.*;
public abstract class Io_stream_rdr__base implements Io_stream_rdr {
public abstract byte Tid();
public Io_url Url() {return url;} protected Io_url url;
public long Len() {return len;} private long len = Io_mgr.Len_null;
public boolean Exists() {return this.Len() > 0;}
public Io_stream_rdr Url_(Io_url v) {this.url = v; return this;}
public Io_stream_rdr Len_(long v) {len = v; return this;}
public Object Under() {return stream;} public Io_stream_rdr Under_(java.io.InputStream v) {this.stream = v; return this;} protected java.io.InputStream stream;
public void Open_mem(byte[] v) {
stream = Wrap_stream(new java.io.ByteArrayInputStream(v));
}
public Io_stream_rdr Open() {
try {stream = Wrap_stream(new java.io.FileInputStream(url.Xto_api()));}
catch (Exception e) {throw Err_.new_exc(e, "io", "open failed", "url", url.Xto_api());}
return this;
}
public int Read(byte[] bry, int bgn, int len) {
try {return stream.read(bry, bgn, len);}
catch (Exception e) {throw Err_.new_exc(e, "io", "read failed", "bgn", bgn, "len", len);}
}
public long Skip(long len) {
try {return stream.skip(len);}
catch (Exception e) {throw Err_.new_exc(e, "io", "skip failed", "len", len);}
}
public void Rls() {
try {stream.close();}
catch (Exception e) {throw Err_.new_exc(e, "io", "close failed", "url", url.Xto_api());}
}
public abstract java.io.InputStream Wrap_stream(java.io.InputStream stream);
}

@ -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.core.ios.streams.rdrs; import gplx.*; import gplx.core.*; import gplx.core.ios.*; import gplx.core.ios.streams.*;
public class Io_stream_rdr__bzip2 extends Io_stream_rdr__base {
@Override public byte Tid() {return Io_stream_tid_.Tid__bzip2;}
@Override public int Read(byte[] bry, int bgn, int len) {
return Io_stream_rdr_.Read_by_parts(stream, Read_len, bry, bgn, len);
}
@Override public java.io.InputStream Wrap_stream(java.io.InputStream stream) {
try {return new org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream(stream, true);}
catch (Exception exc) {throw Err_.new_wo_type("failed to open bzip2 stream");}
}
private static final int Read_len = Io_mgr.Len_mb * 128;
}

@ -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.core.ios.streams.rdrs; import gplx.*; import gplx.core.*; import gplx.core.ios.*; import gplx.core.ios.streams.*;
public class Io_stream_rdr__gzip extends Io_stream_rdr__base {
@Override public byte Tid() {return Io_stream_tid_.Tid__gzip;}
@Override public int Read(byte[] bry, int bgn, int len) {
synchronized (this) {
try {
int total_read = 0;
while (true) { // NOTE: the gz stream reads partially; (request 100; only get back 10); keep reading until entire bfr is full or -1
int read = stream.read(bry, bgn, len);
if (read == Io_stream_rdr_.Read_done) break;
total_read += read;
if (total_read >= len) break; // entire bfr full; stop
bgn += read; // increase bgn by amount read
len -= read; // decrease len by amount read
}
return total_read == 0 ? Io_stream_rdr_.Read_done : total_read; // gzip seems to allow 0 bytes read (bz2 and zip return -1 instead); normalize return to -1;
}
catch (Exception e) {
throw Err_.new_exc(e, "io", "read failed", "bgn", bgn, "len", len);
}
}
}
@Override public java.io.InputStream Wrap_stream(java.io.InputStream stream) {
try {return new java.util.zip.GZIPInputStream(stream);}
catch (Exception exc) {throw Err_.new_wo_type("failed to open gz stream");}
}
}

@ -0,0 +1,30 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.core.ios.streams.rdrs; import gplx.*; import gplx.core.*; import gplx.core.ios.*; import gplx.core.ios.streams.*;
public class Io_stream_rdr__noop implements Io_stream_rdr {
public Object Under() {return null;}
public byte Tid() {return Io_stream_tid_.Tid__null;}
public boolean Exists() {return false;}
public Io_url Url() {return Io_url_.Empty;} public Io_stream_rdr Url_(Io_url v) {return this;}
public long Len() {return Io_mgr.Len_null;} public Io_stream_rdr Len_(long v) {return this;}
public void Open_mem(byte[] v) {}
public Io_stream_rdr Open() {return this;}
public int Read(byte[] bry, int bgn, int len) {return Io_stream_rdr_.Read_done;}
public long Skip(long len) {return Io_stream_rdr_.Read_done;}
public void Rls() {}
}

@ -0,0 +1,37 @@
/*
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.core.ios.streams.rdrs; import gplx.*; import gplx.core.*; import gplx.core.ios.*; import gplx.core.ios.streams.*;
public class Io_stream_rdr__raw extends Io_stream_rdr__base {
public byte Tid() {return Io_stream_tid_.Tid__raw;}
public Io_stream_rdr Open() {
Io_url url = this.Url();
try {
if (!Io_mgr.Instance.Exists(url))
stream = Wrap_stream(new java.io.ByteArrayInputStream(Bry_.Empty));
else {
if (url.Info().EngineKey() == IoEngine_.MemKey)
stream = Wrap_stream(new java.io.ByteArrayInputStream(Io_mgr.Instance.LoadFilBry(url.Xto_api())));
else
stream = Wrap_stream(new java.io.FileInputStream(url.Xto_api()));
}
}
catch (Exception e) {throw Err_.new_exc(e, "io", "open failed", "url", url.Xto_api());}
return this;
}
@Override public java.io.InputStream Wrap_stream(java.io.InputStream stream) {return stream;}
}

@ -0,0 +1,25 @@
/*
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.core.ios.streams.rdrs; import gplx.*; import gplx.core.*; import gplx.core.ios.*; import gplx.core.ios.streams.*;
public class Io_stream_rdr__xz extends Io_stream_rdr__base {
@Override public byte Tid() {return Io_stream_tid_.Tid__xz;}
@Override public java.io.InputStream Wrap_stream(java.io.InputStream stream) {
try {return new org.tukaani.xz.XZInputStream(stream);}
catch (Exception exc) {throw Err_.new_wo_type("failed to open xz stream");}
}
}

@ -0,0 +1,54 @@
/*
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.core.ios.streams.rdrs; import gplx.*; import gplx.core.*; import gplx.core.ios.*; import gplx.core.ios.streams.*;
public class Io_stream_rdr__zip extends Io_stream_rdr__base {
@Override public byte Tid() {return Io_stream_tid_.Tid__gzip;}
public Object Under() {return zip_stream;} private java.util.zip.ZipInputStream zip_stream;
public void Src_bfr_(Bry_bfr v) {this.src_bfr = v;} Bry_bfr src_bfr;
public void Open_mem(byte[] v) {
this.zip_stream = (java.util.zip.ZipInputStream)Wrap_stream(new java.io.ByteArrayInputStream(v));
}
public Io_stream_rdr Open() {
try {this.zip_stream = (java.util.zip.ZipInputStream)Wrap_stream(new java.io.FileInputStream(url.Xto_api()));}
catch (Exception e) {throw Err_.new_exc(e, "io", "open failed", "url", url.Xto_api());}
return this;
}
public int Read(byte[] bry, int bgn, int len) {
try {
while (true){
int read = zip_stream.read(bry, bgn, len);
if (read == Io_stream_rdr_.Read_done) {
if (zip_stream.getNextEntry() == null)
return Io_stream_rdr_.Read_done;
}
else
return read;
}
}
catch (Exception e) {throw Err_.new_exc(e, "io", "read failed", "bgn", bgn, "len", len);}
}
public long Skip(long len) {
try {return zip_stream.skip(len);}
catch (Exception e) {throw Err_.new_exc(e, "io", "skip failed", "len", len);}
}
public void Rls() {
try {zip_stream.close();}
catch (Exception e) {throw Err_.new_exc(e, "io", "close failed", "url", url.Xto_api());}
}
@Override public java.io.InputStream Wrap_stream(java.io.InputStream input_stream) {return new java.util.zip.ZipInputStream(input_stream);}
}

@ -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.core.ios.streams.wtrs; import gplx.*; import gplx.core.*; import gplx.core.ios.*; import gplx.core.ios.streams.*;
public abstract class Io_stream_wtr__base implements Io_stream_wtr {
public abstract byte Tid();
public Io_url Url() {return url;} private Io_url url;
public Io_stream_wtr Url_(Io_url v) {url = v; return this;}
public void Trg_bfr_(Bry_bfr v) {this.trg_bfr = v;} private Bry_bfr trg_bfr;
public byte[] To_ary_and_clear() {return trg_bfr.To_bry_and_clear();}
private java.io.OutputStream zip_stream;
private java.io.ByteArrayOutputStream mem_stream;
@Virtual public Io_stream_wtr Open() {
java.io.OutputStream bry_stream = null;
if (trg_bfr == null) {
if (!Io_mgr.Instance.ExistsFil(url)) Io_mgr.Instance.SaveFilStr(url, "");
try {bry_stream = new java.io.FileOutputStream(url.Raw());}
catch (Exception e) {throw Err_.new_exc(e, "io", "open failed", "url", url.Raw());}
}
else {
mem_stream = new java.io.ByteArrayOutputStream();
bry_stream = mem_stream;
}
zip_stream = Wrap_stream(bry_stream);
return this;
}
public void Write(byte[] bry, int bgn, int len) {
try {zip_stream.write(bry, bgn, len);}
catch (Exception e) {Err_.new_exc(e, "io", "write failed", "bgn", bgn, "len", len);}
}
public void Flush() {
if (trg_bfr != null) {
try {zip_stream.close();} catch (Exception e) {throw Err_.new_exc(e, "io", "flush failed");} // must close zip_stream to flush all bytes
trg_bfr.Add(mem_stream.toByteArray());
}
}
public void Rls() {
try {
if (zip_stream != null) zip_stream.close();
if (mem_stream != null) mem_stream.close();
}
catch (Exception e) {throw Err_.new_exc(e, "io", "close failed", "url", url.Raw());}
}
@Virtual protected java.io.OutputStream Wrap_stream(java.io.OutputStream stream) {throw Err_.new_unimplemented();}
}

@ -0,0 +1,25 @@
/*
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.core.ios.streams.wtrs; import gplx.*; import gplx.core.*; import gplx.core.ios.*; import gplx.core.ios.streams.*;
public class Io_stream_wtr__bzip2 extends Io_stream_wtr__base {
@Override public byte Tid() {return Io_stream_tid_.Tid__bzip2;}
@Override public java.io.OutputStream Wrap_stream(java.io.OutputStream stream) {
try {return new org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream(stream);}
catch (Exception e) {throw Err_.new_exc(e, "io", "failed to open bzip2 stream");}
}
}

@ -0,0 +1,25 @@
/*
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.core.ios.streams.wtrs; import gplx.*; import gplx.core.*; import gplx.core.ios.*; import gplx.core.ios.streams.*;
public class Io_stream_wtr__gzip extends Io_stream_wtr__base {
@Override public byte Tid() {return Io_stream_tid_.Tid__gzip;}
@Override public java.io.OutputStream Wrap_stream(java.io.OutputStream stream) {
try {return new java.util.zip.GZIPOutputStream(stream);}
catch (Exception e) {throw Err_.new_exc(e, "io", "failed to open gz stream");}
}
}

@ -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.core.ios.streams.wtrs; import gplx.*; import gplx.core.*; import gplx.core.ios.*; import gplx.core.ios.streams.*;
public class Io_stream_wtr__raw implements Io_stream_wtr {
public byte Tid() {return Io_stream_tid_.Tid__raw;}
public Io_url Url() {return url;} public Io_stream_wtr Url_(Io_url v) {url = v; return this;} private Io_url url;
public void Trg_bfr_(Bry_bfr v) {trg_bfr = v;} private Bry_bfr trg_bfr;
private IoStream bry_stream;
@Override public Io_stream_wtr Open() {
try {
if (trg_bfr == null)
bry_stream = Io_mgr.Instance.OpenStreamWrite(url);
}
catch (Exception e) {throw Err_.new_exc(e, "io", "open failed", "url", url.Raw());}
return this;
}
public void Write(byte[] bry, int bgn, int len) {
if (trg_bfr == null) {
try {bry_stream.Write(bry, bgn, len);}
catch (Exception e) {throw Err_.new_exc(e, "io", "write failed", "url", url.Raw(), "bgn", bgn, "len", len);}
}
else
trg_bfr.Add_mid(bry, bgn, bgn + len);
}
public byte[] To_ary_and_clear() {
return trg_bfr == null ? Io_mgr.Instance.LoadFilBry(url) : trg_bfr.To_bry_and_clear();
}
public void Flush() {
if (trg_bfr == null)
bry_stream.Flush();
}
public void Rls() {
try {
if (trg_bfr == null)
bry_stream.Rls();
}
catch (Exception e) {throw Err_.new_exc(e, "io", "close failed", "url", url.Raw());}
}
}

@ -0,0 +1,25 @@
/*
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.core.ios.streams.wtrs; import gplx.*; import gplx.core.*; import gplx.core.ios.*; import gplx.core.ios.streams.*;
public class Io_stream_wtr__xz extends Io_stream_wtr__base {
@Override public byte Tid() {return Io_stream_tid_.Tid__xz;}
@Override public java.io.OutputStream Wrap_stream(java.io.OutputStream stream) {
try {return new org.tukaani.xz.XZOutputStream(stream, new org.tukaani.xz.LZMA2Options(org.tukaani.xz.LZMA2Options.PRESET_DEFAULT));}
catch (Exception e) {throw Err_.new_exc(e, "io", "failed to open xz stream");}
}
}

@ -0,0 +1,68 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.core.ios.streams.wtrs; import gplx.*; import gplx.core.*; import gplx.core.ios.*; import gplx.core.ios.streams.*;
public class Io_stream_wtr__zip extends Io_stream_wtr__base {
@Override public byte Tid() {return Io_stream_tid_.Tid__zip;}
private java.util.zip.ZipOutputStream zip_stream;
public Io_url Url() {return url;} public Io_stream_wtr Url_(Io_url v) {url = v; trg_bfr = null; return this;} private Io_url url = Io_url_.Empty;
public void Trg_bfr_(Bry_bfr v) {trg_bfr = v;} private Bry_bfr trg_bfr; private java.io.ByteArrayOutputStream mem_stream;
// rely on zip_stream to close bry_stream
@Override public Io_stream_wtr Open() {
java.io.OutputStream bry_stream;
if (trg_bfr == null) {
if (!Io_mgr.Instance.ExistsFil(url)) Io_mgr.Instance.SaveFilStr(url, ""); // create file if it doesn't exist
try {bry_stream = new java.io.FileOutputStream(url.Xto_api());}
catch (Exception e) {throw Err_.new_exc(e, "io", "open failed", "url", url.Raw());}
}
else {
mem_stream = new java.io.ByteArrayOutputStream();
bry_stream = mem_stream;
}
zip_stream = new java.util.zip.ZipOutputStream(bry_stream);
java.util.zip.ZipEntry entry = new java.util.zip.ZipEntry("file");
try {zip_stream.putNextEntry(entry);}
catch (Exception e) {throw Err_.new_exc(e, "io", "open failed", "url", url.Raw());}
return this;
}
public void Write(byte[] bry, int bgn, int len) {
try {zip_stream.write(bry, bgn, len);}
catch (Exception e) {throw Err_.new_exc(e, "io", "write failed", "url", url.Raw(), "bgn", bgn, "len", len);}
}
public void Flush() {// fixed as of DATE:2014-04-15
try {
zip_stream.closeEntry();
zip_stream.close();
if (trg_bfr != null)
trg_bfr.Add(mem_stream.toByteArray());
zip_stream.flush();
}
catch (Exception e) {throw Err_.new_exc(e, "io", "flush failed", "url", url.Raw());}
}
public void Rls() {
try {
if (zip_stream != null) zip_stream.close();
if (mem_stream != null) mem_stream.close();
}
catch (Exception e) {throw Err_.new_exc(e, "io", "close failed", "url", url.Raw());}
}
public byte[] To_ary_and_clear() {
byte[] rv = trg_bfr.To_bry_and_clear();
this.Rls();
return rv;
}
}

@ -54,7 +54,7 @@ public class Db_data_rdr extends DataRdr_base implements DataRdr {
@Override public gplx.core.ios.streams.Io_stream_rdr ReadRdr(String key) {
try {
java.io.InputStream input_stream = rdr.getBinaryStream(key);
return gplx.core.ios.streams.Io_stream_rdr_.file_(input_stream);
return gplx.core.ios.streams.Io_stream_rdr_.New__raw(input_stream);
}
catch (SQLException e) {return gplx.core.ios.streams.Io_stream_rdr_.Noop;}
}

@ -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.dbs; import gplx.*;
public class Db_sql_ {
public static String Make_by_fmt(String[] lines, Object... args) {
Bry_bfr bfr = Bry_bfr_.New();
int len = lines.length;
for (int i = 0; i < len; ++i) {
if (i != 0) bfr.Add_byte_nl();
bfr.Add_str_u8(lines[i]);
}
String fmt = bfr.To_str_and_clear();
return String_.Format(fmt, args);
}
public static byte[] Escape_arg(byte[] raw) {
int len = raw.length;
Bry_bfr bfr = null;
boolean dirty = false;
for (int i = 0; i < len; ++i) {
byte b = raw[i];
if (b == Byte_ascii.Apos) {
if (bfr == null) {
dirty = true;
bfr = Bry_bfr_.New();
bfr.Add_mid(raw, 0, i);
}
bfr.Add_byte_apos().Add_byte_apos();
}
else {
if (dirty) {
bfr.Add_byte(b);
}
}
}
return dirty ? bfr.To_bry_and_clear() : raw;
}
}

@ -7,6 +7,7 @@
<classpathentry kind="src" path="src"/>
<classpathentry exported="true" kind="lib" path="lib/jtidy_xowa.jar"/>
<classpathentry exported="true" kind="lib" path="lib/luaj_xowa.jar"/>
<classpathentry exported="true" kind="lib" path="lib/icu4j-4_8.jar"/>
<classpathentry exported="true" kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="output" path="bin"/>
</classpath>

@ -0,0 +1,22 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.core.intls.ucas; import gplx.*; import gplx.core.*; import gplx.core.intls.*;
public interface Uca_collator {
void Init(String locale, boolean numeric_ordering);
byte[] Get_sortkey(String s);
}

@ -0,0 +1,25 @@
/*
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.core.intls.ucas; import gplx.*; import gplx.core.*; import gplx.core.intls.*;
public class Uca_collator_ {
public static Uca_collator New(String locale, boolean numeric_ordering) {
Uca_collator rv = new Uca_collator__icu__4_8();
rv.Init(locale, numeric_ordering);
return rv;
}
}

@ -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.core.intls.ucas; import gplx.*; import gplx.core.*; import gplx.core.intls.*;
import java.util.Locale;
import com.ibm.icu.text.CollationKey;
import com.ibm.icu.text.Collator;
import com.ibm.icu.text.RuleBasedCollator;
class Uca_collator__icu__4_8 implements Uca_collator {
private Collator collator;
public void Init(String locale, boolean numeric_ordering) {
try {
this.collator = Collator.getInstance(Locale.forLanguageTag(locale));
if (numeric_ordering) {
RuleBasedCollator rbc = (RuleBasedCollator)collator;
rbc.setNumericCollation(true);
}
} catch (Exception e) {throw Err_.new_wo_type("collator init failed", "err", Err_.Message_lang(e));}
}
public byte[] Get_sortkey(String s) {
CollationKey key = collator.getCollationKey(s);
byte[] src = key.toByteArray();
int src_len = src.length;
byte[] rv = src;
// remove last byte if it is 0 (which it often is)
if (src_len > 0 && src[src_len - 1] == 0) {
int rv_len = src_len - 1;
rv = new byte[rv_len];
for (int i = 0; i < rv_len; ++i)
rv[i] = src[i];
}
return rv;
}
}

@ -0,0 +1,51 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.core.intls.ucas; import gplx.*; import gplx.core.*; import gplx.core.intls.*;
public class Uca_ltr_extractor {
private final boolean numeric;
private final byte[] numeric_heading;
private final Hash_adp_bry numeric_hash;
public Uca_ltr_extractor(boolean numeric) {
this.numeric = numeric;
if (numeric) {
numeric_heading = Bry_.new_a7("0-9");
// create hash of "0", "1", "2", ...
numeric_hash = Hash_adp_bry.cs();
for (int i = 0; i < 10; ++i) {
byte[] digit_bry = Bry_.new_by_int(Byte_ascii.Num_0 + i);
numeric_hash.Add(digit_bry, digit_bry);
}
}
else {
numeric_heading = null;
numeric_hash = null;
}
}
public byte[] Get_1st_ltr(byte[] bry) {
// NOTE: this is simplified and only does numeric logic; MW code loads up all ICU chars via first-letters-root.ser, adds custom chars, sorts them, and then does a binary search to find it; REF:IcuCollation.php!getFirstLetter
int bry_len = bry.length;
if (bry_len == 0) return Bry_.Empty;
byte[] rv = gplx.core.intls.Utf8_.Get_char_at_pos_as_bry(bry, 0);
if (numeric) {
if (numeric_hash.Has(rv))
rv = numeric_heading;
}
return rv;
}
}

@ -22,7 +22,7 @@ public class Io_buffer_rdr_tst {
Io_mgr.Instance.InitEngine_mem();
fil = Io_url_.mem_fil_("mem/byteStreamRdr.txt");
ini_Write("0123456789");
rdr = Io_buffer_rdr.new_(Io_stream_rdr_.file_(fil), 4);
rdr = Io_buffer_rdr.new_(Io_stream_rdr_.New__raw(fil), 4);
} Io_buffer_rdr rdr; Io_url fil;
@After public void teardown() {rdr.Rls();}
@Test public void Bfr_load_all() {

@ -23,7 +23,7 @@ public class Io_stream_rdr_process implements Io_stream_rdr {
private InputStream stream_read;
private String[] process_args;
Io_stream_rdr_process(Io_url process_exe, Io_url stream_url, String[] process_args) {this.process_exe = process_exe; this.url = stream_url; this.process_args = process_args;}
public byte Tid() {return Io_stream_.Tid_bzip2;} // for now, classify as bzip2; not sure if separate tid is necessary
public byte Tid() {return Io_stream_tid_.Tid__bzip2;} // for now, classify as bzip2; not sure if separate tid is necessary
public boolean Exists() {return this.Len() > 0;}
public Io_url Url() {return url;} public Io_stream_rdr Url_(Io_url v) {url = v; return this;} private Io_url url;
public long Len() {return len;} public Io_stream_rdr Len_(long v) {len = v; return this;} private long len;

@ -18,16 +18,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.core.ios; import gplx.*; import gplx.core.*;
import gplx.core.ios.streams.*;
public class Io_stream_zip_mgr {
private Io_stream_wtr wtr_gzip, wtr_zip, wtr_bzip2;
private Io_stream_wtr wtr__gzip, wtr__zip, wtr__bzip2, wtr__xz;
public byte[] Zip(byte type, byte[] val) {
if (type == Io_stream_.Tid_raw) return val;
if (type == Io_stream_tid_.Tid__raw) return val;
Io_stream_wtr wtr = Wtr(type);
wtr.Write(val, 0, val.length);
wtr.Flush();
return wtr.To_ary_and_clear();
}
public byte[] Unzip(byte type, byte[] val) {
if (type == Io_stream_.Tid_raw) return val;
if (type == Io_stream_tid_.Tid__raw) return val;
Io_stream_rdr rdr = Rdr(type);
rdr.Open_mem(val);
return Io_stream_rdr_.Load_all_as_bry(Bry_bfr_.New(), rdr);
@ -35,20 +35,22 @@ public class Io_stream_zip_mgr {
private Io_stream_wtr Wtr(byte type) {
Bry_bfr bfr = Bry_bfr_.New();
switch (type) {
case Io_stream_.Tid_gzip : if (wtr_gzip == null) wtr_gzip = Io_stream_wtr_.new_by_mem(bfr, Io_stream_.Tid_gzip) ; return wtr_gzip.Open();
case Io_stream_.Tid_zip : if (wtr_zip == null) wtr_zip = Io_stream_wtr_.new_by_mem(bfr, Io_stream_.Tid_zip) ; return wtr_zip.Open();
case Io_stream_.Tid_bzip2 : if (wtr_bzip2 == null) wtr_bzip2 = Io_stream_wtr_.new_by_mem(bfr, Io_stream_.Tid_bzip2) ; return wtr_bzip2.Open();
case Io_stream_.Tid_raw :
default : throw Err_.new_unhandled(type);
case Io_stream_tid_.Tid__gzip: if (wtr__gzip == null) wtr__gzip = Io_stream_wtr_.New_by_mem(bfr, Io_stream_tid_.Tid__gzip); return wtr__gzip.Open();
case Io_stream_tid_.Tid__zip: if (wtr__zip == null) wtr__zip = Io_stream_wtr_.New_by_mem(bfr, Io_stream_tid_.Tid__zip); return wtr__zip.Open();
case Io_stream_tid_.Tid__bzip2: if (wtr__bzip2 == null) wtr__bzip2 = Io_stream_wtr_.New_by_mem(bfr, Io_stream_tid_.Tid__bzip2); return wtr__bzip2.Open();
case Io_stream_tid_.Tid__xz: if (wtr__xz == null) wtr__xz = Io_stream_wtr_.New_by_mem(bfr, Io_stream_tid_.Tid__xz); return wtr__xz.Open();
case Io_stream_tid_.Tid__raw:
default: throw Err_.new_unhandled(type);
}
}
private Io_stream_rdr Rdr(byte type) { // TS.MEM: DATE:2016-07-12
switch (type) {
case Io_stream_.Tid_gzip : return Io_stream_rdr_.new_by_tid_(Io_stream_.Tid_gzip);
case Io_stream_.Tid_zip : return Io_stream_rdr_.new_by_tid_(Io_stream_.Tid_zip);
case Io_stream_.Tid_bzip2 : return Io_stream_rdr_.new_by_tid_(Io_stream_.Tid_bzip2);
case Io_stream_.Tid_raw :
default : throw Err_.new_unhandled(type);
case Io_stream_tid_.Tid__gzip: return Io_stream_rdr_.New_by_tid(Io_stream_tid_.Tid__gzip);
case Io_stream_tid_.Tid__zip: return Io_stream_rdr_.New_by_tid(Io_stream_tid_.Tid__zip);
case Io_stream_tid_.Tid__bzip2: return Io_stream_rdr_.New_by_tid(Io_stream_tid_.Tid__bzip2);
case Io_stream_tid_.Tid__xz: return Io_stream_rdr_.New_by_tid(Io_stream_tid_.Tid__xz);
case Io_stream_tid_.Tid__raw:
default: throw Err_.new_unhandled(type);
}
}
}

@ -18,22 +18,23 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.core.net; import gplx.*; import gplx.core.*;
import gplx.core.net.qargs.*;
public class Gfo_url {
public byte[] Raw() {return raw;} private byte[] raw;
public byte Protocol_tid() {return protocol_tid;} private byte protocol_tid;
public byte[] Protocol_bry() {return protocol_bry;} private byte[] protocol_bry;
public byte[] Anch() {return anch;} private byte[] anch;
public Gfo_qarg_itm[] Qargs() {return qargs;} private Gfo_qarg_itm[] qargs;
public byte[][] Segs() {return segs;} private byte[][] segs; private int segs__len;
public byte[] Segs__get_at(int i) {return i < segs__len ? segs[i] : null;}
public byte[] Segs__get_at_1st() {return segs__len > 0 ? segs[0] : null;}
public byte[] Segs__get_at_nth() {return segs__len > 1 ? segs[segs__len - 1] : null;}
public Gfo_url Ctor(byte[] raw, byte protocol_tid, byte[] protocol_bry, byte[][] segs, Gfo_qarg_itm[] qargs, byte[] anch) {
private final int segs__len;
public Gfo_url(byte[] raw, byte protocol_tid, byte[] protocol_bry, byte[][] segs, Gfo_qarg_itm[] qargs, byte[] anch) {
this.raw = raw;
this.protocol_tid = protocol_tid; this.protocol_bry = protocol_bry;
this.segs = segs; this.segs__len = segs.length;
this.qargs = qargs;
this.anch = anch;
return this;
}
public static final Gfo_url Empty = new Gfo_url().Ctor(Bry_.Empty, Gfo_protocol_itm.Tid_unknown, Bry_.Empty, Bry_.Ary_empty, null, null);
public byte[] Raw() {return raw;} private final byte[] raw;
public byte Protocol_tid() {return protocol_tid;} private final byte protocol_tid;
public byte[] Protocol_bry() {return protocol_bry;} private final byte[] protocol_bry;
public byte[] Anch() {return anch;} private final byte[] anch;
public Gfo_qarg_itm[] Qargs() {return qargs;} private final Gfo_qarg_itm[] qargs;
public byte[][] Segs() {return segs;} private final byte[][] segs;
public byte[] Segs__get_at(int i) {return i < segs__len ? segs[i] : null;}
public byte[] Segs__get_at_1st() {return segs__len > 0 ? segs[0] : null;}
public byte[] Segs__get_at_nth() {return segs__len > 1 ? segs[segs__len - 1] : null;}
public static final Gfo_url Empty = new Gfo_url(Bry_.Empty, Gfo_protocol_itm.Tid_unknown, Bry_.Empty, Bry_.Ary_empty, null, null);
}

@ -16,20 +16,21 @@ 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.core.net; import gplx.*; import gplx.core.*;
import gplx.core.primitives.*; import gplx.core.btries.*;
import gplx.core.btries.*;
import gplx.core.net.qargs.*;
import gplx.langs.htmls.encoders.*;
public class Gfo_url_parser {
private final Btrie_slim_mgr protocols = Btrie_slim_mgr.ci_a7(); // ASCII:url_protocol; EX:"http:", "ftp:", etc
private final Bry_ary segs_ary = new Bry_ary(4), qargs = new Bry_ary(4);
private final Bry_bfr tmp_bfr = Bry_bfr_.Reset(500);
private final Btrie_rv trv = new Btrie_rv();
public byte[] Relative_url_protocol_bry() {return Gfo_protocol_itm.Itm_https.Key_w_colon_bry();} // NOTE: https b/c any WMF wiki will now default to WMF; DATE:2015-07-26
private final List_adp segs_list = List_adp_.New(), qargs_list = List_adp_.New();
private final Bry_bfr tmp_bfr = Bry_bfr_.Reset(500);
public Gfo_url_parser() {
Init_protocols(Gfo_protocol_itm.Ary());
Init_protocol_itm(Gfo_protocol_itm.Bry_relative, Gfo_protocol_itm.Tid_relative_1);
Init_protocol_itm(Gfo_protocol_itm.Bry_file, Gfo_protocol_itm.Tid_file);
Init_protocol_itm(gplx.xowa.parsers.lnkes.Xop_lnke_wkr.Bry_xowa_protocol, Gfo_protocol_itm.Tid_xowa);
}
public byte[] Relative_url_protocol_bry() {return Gfo_protocol_itm.Itm_https.Key_w_colon_bry();} // NOTE: https b/c any WMF wiki will now default to WMF; DATE:2015-07-26
private void Init_protocols(Gfo_protocol_itm... itms) {
int len = itms.length;
for (int i = 0; i < len; i++) {
@ -37,9 +38,7 @@ public class Gfo_url_parser {
Init_protocol_itm(itm.Key_w_colon_bry(), itm.Tid());
}
}
public void Init_protocol_itm(byte[] key, byte protocol_tid) {
protocols.Add_bry_byte(key, protocol_tid);
}
public void Init_protocol_itm(byte[] key, byte protocol_tid) {protocols.Add_bry_byte(key, protocol_tid);}
public void Parse_site_fast(Gfo_url_site_data site_data, byte[] src, int src_bgn, int src_end) {
int pos = src_bgn; boolean rel = false;
if (pos + 1 < src_end && src[pos] == Byte_ascii.Slash && src[pos + 1] == Byte_ascii.Slash) { // starts with "//"
@ -62,199 +61,126 @@ public class Gfo_url_parser {
slash_pos = Bry_.Trim_end_pos(src, slash_pos);
site_data.Atrs_set(rel, pos, slash_pos);
}
private static final int Area__path = 1, Area__qarg_key_1st = 2, Area__qarg_key_nth = 3, Area__qarg_val = 4, Area__anch = 5;
private byte[] src; int src_bgn, src_end;
private int area;
private boolean encoded;
private byte protocol_tid; private byte[] protocol_bry, anch;
private int path_bgn, qarg_key_bgn, qarg_val_bgn, anch_bgn, anch_nth_bgn;
public Gfo_url Parse(byte[] src) {return Parse(new Gfo_url(), src, 0, src.length);}
public Gfo_url Parse(Gfo_url rv, byte[] src, int src_bgn, int src_end) {
this.src = src; this.src_bgn = src_bgn; this.src_end = src_end;
encoded = false;
protocol_tid = Gfo_protocol_itm.Tid_null;
protocol_bry = anch = null;
path_bgn = qarg_key_bgn = qarg_val_bgn = anch_bgn = anch_nth_bgn = -1;
segs_ary.Clear(); qargs.Clear();
int pos = src_bgn;
Object protocol_obj = protocols.Match_at(trv, src, src_bgn, src_end);
pos = trv.Pos();
pos = Bry_find_.Find_fwd_while(src, pos, src_end, Byte_ascii.Slash);
if (protocol_obj == null) {
this.protocol_tid = Gfo_protocol_itm.Tid_unknown;
}
else {
this.protocol_tid = ((Byte_obj_val)protocol_obj).Val();
this.protocol_bry = Make_bry(src_bgn, pos);
}
area = Area__path;
path_bgn = pos;
while (true) {
if (pos == src_end) break;
byte b = src[pos];
public Gfo_url Parse(byte[] src) {return Parse(src, 0, src.length);}
public Gfo_url Parse(byte[] src, int src_bgn, int src_end) {
// protocol
byte protocol_tid = protocols.Match_byte_or(trv, src, src_bgn, src_end, Gfo_protocol_itm.Tid_unknown);
int pos = Bry_find_.Find_fwd_while(src, trv.Pos(), src_end, Byte_ascii.Slash); // set pos after last slash; EX: "https://A" -> position before "A"
byte[] protocol_bry = protocol_tid == Gfo_protocol_itm.Tid_unknown
? null
: Make_bry(false, src, src_bgn, pos);
// loop chars and handle "/", "#", "?", and "%"
boolean encoded = false;
int src_zth = src_end - 1;
int anch_bgn = -1, qarg_bgn = -1, seg_bgn = pos;
for (int i = pos; i < src_end; ++i) {
byte b = src[i];
switch (b) {
case Byte_ascii.Slash: pos = Parse_slash(pos, b); break;
case Byte_ascii.Question: pos = Parse_qarg_key_1st(pos, b); break;
case Byte_ascii.Amp: pos = Parse_qarg_key_nth(pos, b); break;
case Byte_ascii.Eq: pos = Parse_qarg_val(pos, b); break;
case Byte_ascii.Hash: if (anch_bgn == -1) pos = Parse_anch(pos, b); else ++pos; break; // anchor begins at 1st #, not last #; EX:A#B#C has anchor of "B#C" not "C" PAGE:en.w:Grand_Central_Terminal; DATE:2015-12-31
case Byte_ascii.Percent: encoded = true; ++pos; break;
default:
++pos;
case Byte_ascii.Slash:
if (qarg_bgn == -1) { // ignore slash in qargs
segs_list.Add(Make_bry(encoded, src, seg_bgn, i));
encoded = false;
seg_bgn = i + 1; // +1 to skip "/"
}
break;
case Byte_ascii.Hash: // set qarg to first #; also, ignore rest of String; EX: A#B#C -> B#C
if (i == src_zth) continue; // ignore # at EOS; EX: "A#"
anch_bgn = i;
i = src_end;
break;
case Byte_ascii.Question: // set qarg to last "?"; EX: A?B?C -> C
if (i == src_zth) continue; // ignore ? at EOS; EX: "A?"
qarg_bgn = i;
break;
case Byte_ascii.Percent:
encoded = true;
break;
}
}
End_area(pos, Byte_ascii.Null);
rv.Ctor(src, protocol_tid, protocol_bry, segs_ary.To_ary(0), Make_qargs(), anch);
return rv;
}
private int Parse_slash(int pos, byte b) {
switch (area) {
case Area__path: return End_area(pos, b);
default: return pos + 1;
}
}
private int Parse_anch(int pos, byte b) {
switch (area) {
case Area__path:
End_area(pos, b);
area = Area__anch;
anch_bgn = pos + 1;
break;
case Area__anch: // handle double; A#B#C -> "A#B", "C"
Append_to_last_path(Byte_ascii.Hash, Make_bry(anch_bgn, pos));
anch_bgn = pos + 1;
break;
case Area__qarg_val:
case Area__qarg_key_1st:
case Area__qarg_key_nth:
if (anch_nth_bgn == -1)
anch_nth_bgn = Bry_find_.Find_bwd(src, Byte_ascii.Hash, src_end);
if (pos == anch_nth_bgn) {
End_area(pos, b);
area = Area__anch;
anch_bgn = pos + 1;
}
break;
default:
break;
}
return pos + 1;
}
private int Parse_qarg_key_1st(int pos, byte b) {
switch (area) {
case Area__path: // only valid way to start qarg; EX: A?B=C
End_area(pos, b);
area = Area__qarg_key_1st;
qarg_key_bgn = pos + 1;
break;
case Area__qarg_key_1st: // handle dupe; EX: A?B?C
case Area__qarg_key_nth: // handle dupe; EX: A?B=C&D?
case Area__qarg_val: // handle dupe; EX: A?B=?
End_area(pos, b);
Append_to_last_path__qargs();
area = Area__qarg_key_1st;
qarg_key_bgn = pos + 1;
break;
int seg_end = src_end; // set seg_end to src_end; EX: "https://site/A" -> "A"; seg_end may be overriden if "#" or "?" exists
// set anch
byte[] anch = null;
if (anch_bgn != -1) {
seg_end = anch_bgn; // set seg_end to anch_bgn; EX: "https://site/A#B" -> "A" x> "A#B"
anch = Make_bry(encoded, src, anch_bgn + 1, src_end); // +1 to skip "#"
}
return pos + 1;
}
private int Parse_qarg_key_nth(int pos, byte b) {
switch (area) {
case Area__path: // ignore if qarg not started; EX: A&B
break;
case Area__qarg_key_1st: // handle invalid; A?B&C
case Area__qarg_key_nth: // handle invalid; A?B=C&D&E=F
End_area(pos, b);
qargs.Add(null);
area = Area__qarg_key_nth;
qarg_key_bgn = pos + 1;
break;
case Area__qarg_val:
End_area(pos, b);
area = Area__qarg_key_nth;
qarg_key_bgn = pos + 1;
break;
// set qargs
Gfo_qarg_itm[] qarg_ary = Gfo_qarg_itm.Ary_empty;
if (qarg_bgn != -1) {
int qarg_end = anch_bgn == -1
? src_end // # missing; set to src_end; EX: "A?B=C" -> EOS
: anch_bgn; // # exists; set to anch_bgn; EX: "A?B=C#D" -> #
qarg_ary = Make_qarg_ary(src, qarg_bgn, qarg_end);
seg_end = qarg_ary.length == 0
? src_end // set seg_end to src_end if pseudo qarg; EX: "https://site/A?B" -> "A?B" x> "A"
: qarg_bgn; // set seg_end to qarg_bgn; EX: "https://site/A?B=C" -> "A" x> "A#B"; NOTE: overrides anch; "A?B=C#D" -> "A"
}
return pos + 1;
// extract seg_end; note that there will always be a seg_end; if src ends with slash, then it will be ""; EX: "A/" -> "A", ""
segs_list.Add(Make_bry(encoded, src, seg_bgn, seg_end));
// build url and return it
return new Gfo_url(src, protocol_tid, protocol_bry, (byte[][])segs_list.To_ary_and_clear(byte[].class), qarg_ary, anch);
}
private int Parse_qarg_val(int pos, byte b) {
switch (area) {
case Area__qarg_key_1st:
case Area__qarg_key_nth:
End_area(pos, b); break;
default: break;
}
return pos + 1;
}
private int End_area(int pos, byte b) {
switch (area) {
case Area__path:
segs_ary.Add(Make_bry(path_bgn, pos));
path_bgn = pos + 1;
break;
case Area__qarg_key_1st:
case Area__qarg_key_nth:
if (b == Byte_ascii.Null && qargs.Len() == 0) // handle A?b but not A?b=c&d
Append_to_last_path(Byte_ascii.Question, Make_bry(qarg_key_bgn, src_end));
else {
qargs.Add(Make_bry(qarg_key_bgn, pos));
qarg_val_bgn = pos + 1;
area = Area__qarg_val;
}
break;
case Area__qarg_val:
qargs.Add(Make_bry(qarg_val_bgn, pos));
qarg_key_bgn = pos + 1;
qarg_val_bgn = -1;
area = Area__qarg_key_nth;
break;
case Area__anch:
if (b == Byte_ascii.Null && anch_bgn == src_end) // handle A# but not "A#B"
Append_to_last_path(Byte_ascii.Hash, Make_bry(anch_bgn, src_end));
else
anch = Make_bry(anch_bgn, pos);
break;
default:
break;
}
encoded = false;
return pos + 1;
}
private byte[] Make_bry(int bgn, int end) {
return encoded ? gplx.langs.htmls.encoders.Gfo_url_encoder_.Xourl.Decode(tmp_bfr, Bool_.N, src, bgn, end).To_bry_and_clear() : Bry_.Mid(src, bgn, end);
}
private Gfo_qarg_itm[] Make_qargs() {
int qargs_len = qargs.Len(); if (qargs_len == 0) return Gfo_qarg_itm.Ary_empty;
if (qargs_len % 2 == 1) ++qargs_len; // handle odd qargs; EX: ?A=B&C&D=E
Gfo_qarg_itm[] rv = new Gfo_qarg_itm[qargs_len / 2];
for (int i = 0; i < qargs_len; i += 2) {
byte[] key = qargs.Get_at(i);
int val_idx = i + 1;
byte[] val = val_idx < qargs_len ? qargs.Get_at(val_idx) : null;
rv[i / 2] = new Gfo_qarg_itm(key, val);
}
return rv;
}
private void Append_to_last_path(byte b, byte[] append) {
byte[] last_path = segs_ary.Get_at_last(); if (last_path == null) return;
last_path = Bry_.Add_w_dlm(b, last_path, append);
segs_ary.Set_at_last(last_path);
}
private void Append_to_last_path__qargs() {
byte[] last_path = segs_ary.Get_at_last(); if (last_path == null) return;
tmp_bfr.Add(last_path);
int len = qargs.Len();
if (len % 2 == 1) qargs.Add(null); // handle odd qargs
for (int i = 0; i < len; i += 2) {
tmp_bfr.Add_byte(i == 0 ? Byte_ascii.Question : Byte_ascii.Amp);
tmp_bfr.Add(qargs.Get_at(i));
byte[] qarg_val = qargs.Get_at(i + 1);
if (qarg_val != null) // handle "null" added above
tmp_bfr.Add_byte_eq().Add(qarg_val);
private Gfo_qarg_itm[] Make_qarg_ary(byte[] src, int qarg_bgn, int qarg_end) {
// init
int key_bgn = qarg_bgn + 1; // +1 to skip "?"
byte[] key_bry = null;
int val_bgn = -1;
boolean encoded = false;
// loop qarg for "&", "=", "%"
int qarg_pos = qarg_bgn;
while (true) {
boolean b_is_last = qarg_pos == qarg_end;
byte b = b_is_last ? Byte_ascii.Null : src[qarg_pos];
boolean make_qarg = false;
switch (b) {
case Byte_ascii.Amp: // "&" always makes qarg
make_qarg = true;
break;
case Byte_ascii.Null: // "EOS" makes qarg as long as "=" seen or at least one qarg; specifically, "A?B" shouldn't make qarg
if ( val_bgn != -1 // "=" seen; EX: "?A=B"
|| qargs_list.Count() > 0) // at least one qarg exists; EX: "?A=B&C"
make_qarg = true;
break;
case Byte_ascii.Eq:
key_bry = Make_bry(encoded, src, key_bgn, qarg_pos);
encoded = false;
val_bgn = qarg_pos + 1;
break;
case Byte_ascii.Percent:
encoded = true;
break;
}
// make qarg
if (make_qarg) {
byte[] val_bry = null;
if (key_bry == null) // key missing; EX: "&A" -> "A,null"
key_bry = Make_bry(encoded, src, key_bgn, qarg_pos);
else // key exists; EX: "&A=B" -> "A,B"
val_bry = Make_bry(encoded, src, val_bgn, qarg_pos);
encoded = false;
qargs_list.Add(new Gfo_qarg_itm(key_bry, val_bry));
// reset vars
key_bry = null;
key_bgn = qarg_pos + 1;
val_bgn = -1;
}
if (b_is_last) break;
++qarg_pos;
}
qargs.Clear();
segs_ary.Set_at_last(tmp_bfr.To_bry_and_clear());
return (Gfo_qarg_itm[])qargs_list.To_ary_and_clear(Gfo_qarg_itm.class);
}
private byte[] Make_bry(boolean encoded, byte[] src, int bgn, int end) {
return encoded ? Gfo_url_encoder_.Xourl.Decode(tmp_bfr, Bool_.N, src, bgn, end).To_bry_and_clear() : Bry_.Mid(src, bgn, end);
}
public static final byte[] Bry_double_slash = new byte[] {Byte_ascii.Slash, Byte_ascii.Slash};
}

@ -20,15 +20,19 @@ import gplx.core.net.qargs.*;
class Gfo_url_parser_fxt {
private final Gfo_url_parser parser = new Gfo_url_parser();
private Gfo_url actl;
public Gfo_url_parser_fxt Chk_protocol_tid(byte v) {Tfds.Eq_byte(v, actl.Protocol_tid(), "protocol_tid"); return this;}
public Gfo_url_parser_fxt Chk_protocol_bry(String v) {Tfds.Eq_str(v, actl.Protocol_bry(), "protocol_bry"); return this;}
public Gfo_url_parser_fxt Chk_site(String v) {Tfds.Eq_str(v, actl.Segs__get_at_1st(), "site"); return this;}
public Gfo_url_parser_fxt Chk_page(String v) {Tfds.Eq_str(v, actl.Segs__get_at_nth(), "page"); return this;}
public Gfo_url_parser_fxt Chk_anch(String v) {Tfds.Eq_str(v, actl.Anch(), "anch"); return this;}
public Gfo_url_parser_fxt Chk_segs(String... ary) {Tfds.Eq_int(ary.length, actl.Segs().length, "segs_len"); Tfds.Eq_str_lines(String_.Concat_lines_nl(ary), String_.Concat_lines_nl(String_.Ary(actl.Segs())), "segs"); return this;}
public Gfo_url_parser_fxt Chk_qargs(String... ary) {Tfds.Eq_str_lines(String_.To_str__as_kv_ary(ary), Gfo_qarg_itm.To_str(actl.Qargs()), "qargs"); return this;}
public Gfo_url_parser_fxt Run_parse(String v) {
this.actl = parser.Parse(Bry_.new_u8(v));
public Gfo_url_parser_fxt Test__protocol_tid(byte v) {Tfds.Eq_byte(v, actl.Protocol_tid(), "protocol_tid"); return this;}
public Gfo_url_parser_fxt Test__protocol_bry(String v) {Tfds.Eq_str(v, actl.Protocol_bry(), "protocol_bry"); return this;}
public Gfo_url_parser_fxt Test__site(String v) {Tfds.Eq_str(v, actl.Segs__get_at_1st(), "site"); return this;}
public Gfo_url_parser_fxt Test__page(String v) {Tfds.Eq_str(v, actl.Segs__get_at_nth(), "page"); return this;}
public Gfo_url_parser_fxt Test__anch(String v) {Tfds.Eq_str(v, actl.Anch(), "anch"); return this;}
public Gfo_url_parser_fxt Test__segs(String... ary) {
Tfds.Eq_str_lines(String_.Concat_lines_nl(ary), String_.Concat_lines_nl(String_.Ary(actl.Segs())), "segs");
Tfds.Eq_int(ary.length, actl.Segs().length, "segs_len");
return this;
}
public Gfo_url_parser_fxt Test__qargs(String... ary) {Tfds.Eq_str_lines(String_.To_str__as_kv_ary(ary), Qargs__To_str(actl.Qargs()), "qargs"); return this;}
public Gfo_url_parser_fxt Exec__parse(String v) {
this.actl = parser.Parse(Bry_.new_u8(v), 0, String_.Len(v));
return this;
}
public void Test_Parse_site_fast(String raw, String expd) {
@ -37,4 +41,16 @@ class Gfo_url_parser_fxt {
String actl = String_.new_u8(raw_bry, site_data.Site_bgn(), site_data.Site_end());
Tfds.Eq(expd, actl);
} private final Gfo_url_site_data site_data = new Gfo_url_site_data();
private static String Qargs__To_str(Gfo_qarg_itm[] ary) {
int len = ary.length;
Bry_bfr bfr = Bry_bfr_.New();
for (int i = 0; i < len; ++i) {
Gfo_qarg_itm itm = ary[i];
bfr.Add(itm.Key_bry()).Add_byte_eq();
if (itm.Val_bry() != null)
bfr.Add(itm.Val_bry());
bfr.Add_byte_nl();
}
return bfr.To_str_and_clear();
}
}

@ -18,102 +18,102 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.core.net; import gplx.*; import gplx.core.*;
import org.junit.*;
public class Gfo_url_parser_tst {
private final Gfo_url_parser_fxt tstr = new Gfo_url_parser_fxt();
private final Gfo_url_parser_fxt tstr = new Gfo_url_parser_fxt();
@Test public void Protocol__relative() {
tstr.Run_parse("//en.wikipedia.org").Chk_protocol_tid(Gfo_protocol_itm.Tid_relative_1).Chk_protocol_bry("//").Chk_site("en.wikipedia.org");
tstr.Exec__parse("//en.wikipedia.org").Test__protocol_tid(Gfo_protocol_itm.Tid_relative_1).Test__protocol_bry("//").Test__site("en.wikipedia.org");
}
@Test public void Protocol__none() {
tstr.Run_parse("en.wikipedia.org/wiki/A").Chk_protocol_tid(Gfo_protocol_itm.Tid_unknown).Chk_segs("en.wikipedia.org", "wiki", "A");
tstr.Exec__parse("en.wikipedia.org/wiki/A").Test__protocol_tid(Gfo_protocol_itm.Tid_unknown).Test__segs("en.wikipedia.org", "wiki", "A");
}
@Test public void Site__parts__3() {
tstr.Run_parse("https://en.wikipedia.org").Chk_protocol_tid(Gfo_protocol_itm.Tid_https).Chk_protocol_bry("https://").Chk_segs("en.wikipedia.org");
tstr.Exec__parse("https://en.wikipedia.org").Test__protocol_tid(Gfo_protocol_itm.Tid_https).Test__protocol_bry("https://").Test__segs("en.wikipedia.org");
}
@Test public void Site__parts__2() {
tstr.Run_parse("https://wikipedia.org").Chk_protocol_tid(Gfo_protocol_itm.Tid_https).Chk_segs("wikipedia.org");
tstr.Exec__parse("https://wikipedia.org").Test__protocol_tid(Gfo_protocol_itm.Tid_https).Test__segs("wikipedia.org");
}
@Test public void Site__parts__1() {
tstr.Run_parse("https://wikipedia").Chk_protocol_tid(Gfo_protocol_itm.Tid_https).Chk_segs("wikipedia");
tstr.Exec__parse("https://wikipedia").Test__protocol_tid(Gfo_protocol_itm.Tid_https).Test__segs("wikipedia");
}
@Test public void Site__slash__none() {
tstr.Run_parse("https:site").Chk_protocol_tid(Gfo_protocol_itm.Tid_https).Chk_site("site");
tstr.Exec__parse("https:site").Test__protocol_tid(Gfo_protocol_itm.Tid_https).Test__site("site");
}
@Test public void Site__slash__eos() {
tstr.Exec__parse("https://en.wikipedia.org/").Test__protocol_tid(Gfo_protocol_itm.Tid_https).Test__site("en.wikipedia.org");
}
@Test public void Paths__1() {
tstr.Run_parse("https://site/A").Chk_segs("site", "A");
tstr.Exec__parse("https://site/A").Test__segs("site", "A");
}
@Test public void Paths__2() {
tstr.Run_parse("https://site/wiki/A").Chk_segs("site", "wiki", "A");
tstr.Exec__parse("https://site/wiki/A").Test__segs("site", "wiki", "A");
}
@Test public void Paths__n() {
tstr.Run_parse("https://site/wiki/A/B/C/D").Chk_segs("site", "wiki", "A", "B", "C", "D");
tstr.Exec__parse("https://site/wiki/A/B/C/D").Test__segs("site", "wiki", "A", "B", "C", "D");
}
@Test public void Qargs__1() {
tstr.Run_parse("https://site/A?B=C").Chk_page("A").Chk_qargs("B", "C");
tstr.Exec__parse("https://site/A?B=C").Test__page("A").Test__qargs("B", "C");
}
@Test public void Qargs__2() {
tstr.Run_parse("https://site/A?B=C&D=E").Chk_page("A").Chk_qargs("B", "C", "D", "E");
tstr.Exec__parse("https://site/A?B=C&D=E").Test__page("A").Test__qargs("B", "C", "D", "E");
}
@Test public void Qargs__3() {
tstr.Run_parse("https://site/A?B=C&D=E&F=G").Chk_page("A").Chk_qargs("B", "C", "D", "E", "F", "G");
tstr.Exec__parse("https://site/A?B=C&D=E&F=G").Test__page("A").Test__qargs("B", "C", "D", "E", "F", "G");
}
@Test public void Qargs__ques__dupe__ques() {
tstr.Run_parse("https://site/A?B?Y=Z").Chk_page("A?B").Chk_qargs("Y", "Z");
tstr.Exec__parse("https://site/A?B?Y=Z").Test__page("A?B").Test__qargs("Y", "Z");
}
@Test public void Qargs__ques__dupe__amp() {
tstr.Run_parse("https://site/A?B=C&D?Y=Z").Chk_page("A?B=C&D").Chk_qargs("Y", "Z");
tstr.Exec__parse("https://site/A?B=C&D?Y=Z").Test__page("A?B=C&D").Test__qargs("Y", "Z");
}
@Test public void Qargs__ques__dupe__eq() {
tstr.Run_parse("https://site/A?B=C?Y=Z").Chk_page("A?B=C").Chk_qargs("Y", "Z");
tstr.Exec__parse("https://site/A?B=C?Y=Z").Test__page("A?B=C").Test__qargs("Y", "Z");
}
@Test public void Qargs__amp__dupe__ques() {
tstr.Run_parse("https://site/A?B&Y=Z").Chk_page("A").Chk_qargs("B", null, "Y", "Z");
tstr.Exec__parse("https://site/A?B&Y=Z").Test__page("A").Test__qargs("B", null, "Y", "Z");
}
@Test public void Qargs__amp__dupe__amp() {
tstr.Run_parse("https://site/A?B=C&D&Y=Z").Chk_page("A").Chk_qargs("B", "C", "D", null, "Y", "Z");
tstr.Exec__parse("https://site/A?B=C&D&Y=Z").Test__page("A").Test__qargs("B", "C", "D", null, "Y", "Z");
}
@Test public void Qargs__missing_val__0() {
tstr.Run_parse("https://site/A?").Chk_page("A?").Chk_qargs();
tstr.Exec__parse("https://site/A?").Test__page("A?").Test__qargs();
}
@Test public void Qargs__missing_val__2() {
tstr.Run_parse("https://site/A?B=C&D&F=G").Chk_page("A").Chk_qargs("B", "C", "D", null, "F", "G");
tstr.Exec__parse("https://site/A?B=C&D&F=G").Test__page("A").Test__qargs("B", "C", "D", null, "F", "G");
}
@Test public void Qargs__missing_val__n() {
tstr.Run_parse("https://site/A?B=C&D=E&F").Chk_page("A").Chk_qargs("B", "C", "D", "E", "F", null);
tstr.Exec__parse("https://site/A?B=C&D=E&F").Test__page("A").Test__qargs("B", "C", "D", "E", "F", null);
}
@Test public void Qargs__site_less__missing__0() {
tstr.Run_parse("A?B").Chk_segs("A?B").Chk_qargs();
tstr.Exec__parse("A?B").Test__segs("A?B").Test__qargs();
}
@Test public void Qargs__site_less() {
tstr.Run_parse("A?B=C&D=E").Chk_site("A").Chk_qargs("B", "C", "D", "E");
tstr.Exec__parse("A?B=C&D=E").Test__site("A").Test__qargs("B", "C", "D", "E");
}
@Test public void Anch__basic() {
tstr.Run_parse("https://site/A#B").Chk_page("A").Chk_anch("B");
tstr.Exec__parse("https://site/A#B").Test__page("A").Test__anch("B");
}
@Test public void Anch__repeat__2() {
tstr.Run_parse("https://site/A#B#C").Chk_page("A").Chk_anch("B#C");
tstr.Exec__parse("https://site/A#B#C").Test__page("A").Test__anch("B#C");
}
@Test public void Anch__repeat__3() {
tstr.Run_parse("https://site/A#B#C#D").Chk_page("A").Chk_anch("B#C#D");
tstr.Exec__parse("https://site/A#B#C#D").Test__page("A").Test__anch("B#C#D");
}
@Test public void Anch__missing() {
tstr.Run_parse("https://site/A#").Chk_page("A#").Chk_anch(null);
tstr.Exec__parse("https://site/A#").Test__page("A#").Test__anch(null);
}
@Test public void Anch__missing__eos() {
tstr.Run_parse("https://site/A#B#").Chk_page("A").Chk_anch("B#");
tstr.Exec__parse("https://site/A#B#").Test__page("A").Test__anch("B#");
}
@Test public void Anch__qargs__basic() {
tstr.Run_parse("https://site/A?B=C&D=E#F").Chk_page("A").Chk_qargs("B", "C", "D", "E").Chk_anch("F");
}
@Test public void Anch__qargs__repeat() {
tstr.Run_parse("https://site/A?B=C#&D=E#F").Chk_page("A").Chk_qargs("B", "C#", "D", "E").Chk_anch("F");
tstr.Exec__parse("https://site/A?B=C&D=E#F").Test__page("A").Test__qargs("B", "C", "D", "E").Test__anch("F");
}
@Test public void Anch__site_less() {
tstr.Run_parse("A#B").Chk_site("A").Chk_anch("B");
tstr.Exec__parse("A#B").Test__site("A").Test__anch("B");
}
@Test public void Encode__page() {
tstr.Run_parse("http://site/A%27s").Chk_site("site").Chk_page("A's");
tstr.Exec__parse("http://site/A%27s").Test__site("site").Test__page("A's");
}
@Test public void Protocol_less__qargs() {
tstr.Run_parse("Special:Search/Earth?fulltext=yes").Chk_segs("Special:Search", "Earth").Chk_page("Earth").Chk_qargs("fulltext", "yes");
tstr.Exec__parse("Special:Search/Earth?fulltext=yes").Test__segs("Special:Search", "Earth").Test__page("Earth").Test__qargs("fulltext", "yes");
}
@Test public void Parse_site_fast() {
tstr.Test_Parse_site_fast("http://a.org/B" , "a.org");
@ -121,4 +121,8 @@ public class Gfo_url_parser_tst {
tstr.Test_Parse_site_fast("//a.org/B" , "a.org");
tstr.Test_Parse_site_fast("//a.org/B:C" , "a.org");
}
// DELETED: logic isn't right; anch is first # not last; EX: https://en.wikipedia.org/w/index.php?title=Category:2001_albums&pagefrom=Beautiful+#View#mw-pages; DATE:2016-10-10
// @Test public void Anch__qargs__repeat() {
// tstr.Exec__parse("https://site/A?B=C#&D=E#F").Test__page("A").Test__qargs("B", "C#", "D", "E").Test__anch("F");
// }
}

@ -17,35 +17,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.core.net.qargs; import gplx.*; import gplx.core.*; import gplx.core.net.*;
public class Gfo_qarg_itm {
public Gfo_qarg_itm(byte[] key_bry, byte[] val_bry) {this.key_bry = key_bry; this.val_bry = val_bry;}
public byte[] Key_bry() {return key_bry;} private byte[] key_bry;
public byte[] Val_bry() {return val_bry;} private byte[] val_bry;
public Gfo_qarg_itm Val_bry_(byte[] v) {val_bry = v; return this;}
public static final Gfo_qarg_itm[] Ary_empty = new Gfo_qarg_itm[0];
public static Gfo_qarg_itm new_key_(String key) {return new Gfo_qarg_itm(Bry_.new_u8(key), Bry_.Empty);}
public static Gfo_qarg_itm[] Ary(String... kvs) {
int len = kvs.length;
Gfo_qarg_itm[] rv = new Gfo_qarg_itm[len / 2];
String key = null;
for (int i = 0; i < len; ++i) {
String s = kvs[i];
if (i % 2 == 0)
key = s;
else
rv[i / 2] = new Gfo_qarg_itm(Bry_.new_u8(key), Bry_.new_u8(s));
}
return rv;
}
public static String To_str(Gfo_qarg_itm[] ary) {
int len = ary.length;
Bry_bfr bfr = Bry_bfr_.New();
for (int i = 0; i < len; ++i) {
Gfo_qarg_itm itm = ary[i];
bfr.Add(itm.Key_bry()).Add_byte_eq();
if (itm.Val_bry() != null)
bfr.Add(itm.Val_bry());
bfr.Add_byte_nl();
}
return bfr.To_str_and_clear();
public Gfo_qarg_itm(byte[] key_bry, byte[] val_bry) {
this.key_bry = key_bry;
this.val_bry = val_bry;
}
public byte[] Key_bry() {return key_bry;} private final byte[] key_bry;
public byte[] Val_bry() {return val_bry;} private byte[] val_bry;
public void Val_bry_(byte[] v) {val_bry = v;}
public static final Gfo_qarg_itm[] Ary_empty = new Gfo_qarg_itm[0];
}

@ -48,8 +48,7 @@ public class Fsd_bin_tbl implements Rls_able {
stmt_insert = conn.Stmt_insert(tbl_name, flds);
tmp_bfr = Bry_bfr_.Reset(Io_mgr.Len_kb);
}
byte[] bin_ary = null;
bin_ary = Io_stream_rdr_.Load_all_as_bry(tmp_bfr, bin_rdr);
byte[] bin_ary = Io_stream_rdr_.Load_all_as_bry(tmp_bfr, bin_rdr);
stmt_insert.Clear()
.Val_int(fld_owner_id, id)
.Val_byte(fld_owner_tid, tid)
@ -62,7 +61,7 @@ public class Fsd_bin_tbl implements Rls_able {
byte[] rv = Select(owner_id, null);
return rv == null
? Io_stream_rdr_.Noop
: Io_stream_rdr_.mem_(rv);
: Io_stream_rdr_.New__mem(rv);
}
public boolean Select_to_url(int owner_id, Io_url url) {
saved_in_parts.Val_n();

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

@ -36,7 +36,7 @@ public class Xoa_app_fxt {
Io_url user_dir = root_dir.GenSubDir_nest("user", "test_user");
Gfo_usr_dlg__log_base.Instance.Log_dir_(user_dir.GenSubDir_nest("tmp", "current"));
Xoae_app app = new Xoae_app(Gfo_usr_dlg_.Test(), Xoa_app_mode.Itm_cmd, root_dir, root_dir.GenSubDir("wiki"), root_dir.GenSubDir("file"), user_dir, root_dir.GenSubDir_nest("user", "anonymous", "wiki"), op_sys);
app.Setup_mgr().Dump_mgr().Data_storage_format_(gplx.core.ios.streams.Io_stream_.Tid_raw); // TEST: set data_storage_format to file, else bldr tests will fails (expects plain text)
app.Setup_mgr().Dump_mgr().Data_storage_format_(gplx.core.ios.streams.Io_stream_tid_.Tid__raw); // TEST: set data_storage_format to file, else bldr tests will fails (expects plain text)
GfsCore.Instance.Clear(); // NOTE: must clear
GfsCore.Instance.AddCmd(app, Xoae_app.Invk_app); // NOTE: must add app to GfsCore; app.Gfs_mgr() always adds current app to GfsCore; note this causes old test to leave behind GfsCore for new test
GfsCore.Instance.AddCmd(app, Xoae_app.Invk_xowa); // add alias for app; DATE:2014-06-09

@ -21,6 +21,7 @@ import gplx.xowa.htmls.hrefs.*;
public class Xoa_url {
public int Tid() {return tid;} private int tid;
public byte[] Raw() {return raw;} private byte[] raw = Bry_.Empty;
public byte[] Orig() {return orig;} private byte[] orig;
public byte[] Wiki_bry() {return wiki_bry;} public Xoa_url Wiki_bry_(byte[] v) {wiki_bry = v; return this;} private byte[] wiki_bry;
public byte[] Page_bry() {return page_bry;} public Xoa_url Page_bry_(byte[] v) {page_bry = v; return this;} private byte[] page_bry;
public byte[] Anch_bry() {return anch_bry;} public Xoa_url Anch_bry_(byte[] v) {anch_bry = v; return this;} private byte[] anch_bry;
@ -35,10 +36,10 @@ public class Xoa_url {
public boolean Wiki_is_missing() {return wiki_is_missing;} private boolean wiki_is_missing;
public boolean Wiki_is_same() {return wiki_is_same;} private boolean wiki_is_same;
public boolean Page_is_main() {return page_is_main;} private boolean page_is_main;
public Xoa_url Ctor(int tid, byte[] raw, byte protocol_tid, byte[] protocol_bry, boolean protocol_is_relative
public Xoa_url Ctor(int tid, byte[] orig, byte[] raw, byte protocol_tid, byte[] protocol_bry, boolean protocol_is_relative
, byte[] wiki, byte[] page, Gfo_qarg_itm[] qargs, byte[] anch
, byte[][] segs_ary, byte[] vnt_bry, boolean wiki_is_missing, boolean wiki_is_same, boolean page_is_main) {
this.tid = tid; this.raw = raw;
this.tid = tid; this.orig = orig; this.raw = raw;
this.protocol_tid = protocol_tid; this.protocol_bry = protocol_bry; this.protocol_is_relative = protocol_is_relative;
this.wiki_bry = wiki; this.page_bry = page; this.qargs_ary = qargs; this.anch_bry = anch;
this.segs_ary = segs_ary; this.vnt_bry = vnt_bry;
@ -92,21 +93,16 @@ public class Xoa_url {
if (tid_is_anch)
page = null;
}
byte[] rv = Bry_.Add
( wiki, wiki_spr // add wiki_key; EX: "en.wikipedia.org", "/wiki/"
, page // add page; EX: "A"
, anch_spr, anch // add anch EX: "#", "B"
);
Bry_bfr bfr = Bry_bfr_.New();
bfr.Add_safe(wiki).Add_safe(wiki_spr); // add wiki_key; EX: "en.wikipedia.org", "/wiki/"
bfr.Add_safe(page); // add page; EX: "A"
if (show_qargs || qargs_ary.length > 0) {
Bry_bfr bfr = Bry_bfr_.New();
try {
bfr.Add(rv);
Gfo_qarg_mgr_old.Concat_bfr(bfr, gplx.langs.htmls.encoders.Gfo_url_encoder_.Href, qargs_ary);
return bfr.To_bry_and_clear();
} finally {bfr.Mkr_rls();}
Gfo_qarg_mgr_old.Concat_bfr(bfr, gplx.langs.htmls.encoders.Gfo_url_encoder_.Href, qargs_ary);
}
else
return rv;
if (anch != null) // NOTE: anch must go last (after qargs); DATE:2016-10-08
bfr.Add(anch_spr).Add(anch); // add anch EX: "#", "B"
return bfr.To_bry_and_clear();
}
public static final Xoa_url Null = null;
public static Xoa_url blank() {return new Xoa_url();}

@ -20,7 +20,7 @@ import gplx.core.primitives.*; import gplx.core.brys.*; import gplx.core.ios.*;
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.addons.wikis.ctgs.htmls.pageboxs.*;
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.addons.wikis.ctgs.htmls.catpages.*;
import gplx.xowa.parsers.*;
import gplx.xowa.apps.urls.*;
public interface Xow_wiki extends Xow_ttl_parser, Gfo_invk {
@ -46,7 +46,8 @@ 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();
Xoctg_pagebox_wtr Ctg__pagebox_wtr();
Xoctg_catpage_mgr Ctg__catpage_mgr();
boolean Html__css_installing(); void Html__css_installing_(boolean v);
Xow_msg_mgr Msg_mgr();
byte[] Wtxt__expand_tmpl(byte[] src);

@ -29,7 +29,7 @@ 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.wikis.ctgs.htmls.pageboxs.*;
import gplx.xowa.addons.*; import gplx.xowa.addons.wikis.htmls.css.mgrs.*; import gplx.xowa.addons.wikis.ctgs.htmls.pageboxs.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.*;
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) {
@ -78,6 +78,7 @@ public class Xowe_wiki implements Xow_wiki, Gfo_invk, Gfo_evt_itm {
cache_mgr = new Xow_cache_mgr(this);
/*if (Bry_.Eq(domain_bry, Xow_domain_itm_.Bry__home))*/ xwiki_mgr.Add_by_atrs(domain_bry, domain_bry); // add full name to xwiki_mgr; needed for lookup in home ns; EX: [[home:Help/Contents]]
this.lnki_bldr = new Xoh_lnki_bldr(app, href_wtr);
this.ctg_catpage_mgr = new Xoctg_catpage_mgr(this);
}
public Gfo_evt_mgr Evt_mgr() {return ev_mgr;} private final Gfo_evt_mgr ev_mgr;
public Xow_ns_mgr Ns_mgr() {return ns_mgr;} private final Xow_ns_mgr ns_mgr;
@ -105,7 +106,8 @@ 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 Xoctg_pagebox_wtr Ctg__pagebox_wtr() {return ctg_pagebox_wtr;} private final Xoctg_pagebox_wtr ctg_pagebox_wtr = new Xoctg_pagebox_wtr();
public Xoctg_catpage_mgr Ctg__catpage_mgr() {return ctg_catpage_mgr;} private final Xoctg_catpage_mgr ctg_catpage_mgr;
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();
@ -266,6 +268,7 @@ public class Xowe_wiki implements Xow_wiki, Gfo_invk, Gfo_evt_itm {
else if (ctx.Match(k, Invk_maint)) return maint_mgr;
else if (ctx.Match(k, Invk_domain)) return domain_str;
else if (ctx.Match(k, Invk_xtns)) return xtn_mgr;
else if (ctx.Match(k, Invk_catpage_mgr)) return ctg_catpage_mgr;
else if (ctx.Match(k, Invk_hdump_enabled_)) this.html_mgr__hdump_enabled = m.ReadYn("v");
else if (ctx.Match(k, gplx.xowa.apps.apis.xowa.wikis.langs.Xoap_lang_variants.Evt_current_changed)) lang.Vnt_mgr().Cur_itm_(m.ReadBry("v"));
else return Gfo_invk_.Rv_unhandled;
@ -280,6 +283,7 @@ public class Xowe_wiki implements Xow_wiki, Gfo_invk, Gfo_evt_itm {
, Invk_xtns = "xtns", Invk_import_mgr = "import"
, Invk_db_mgr_to_sql_ = "db_mgr_to_sql_"
, Invk_domain = "domain", Invk_maint = "maint", Invk_hdump_enabled_ = "hdump_enabled_"
, Invk_catpage_mgr = "catpage_mgr"
;
public static final String Invk_db_mgr = "db_mgr"; // SERIALIZED:000.sqlite3|xowa_cfg
public static final String Invk_lang_ = "lang_";

@ -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.cfgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.bldrs.*;
package gplx.xowa.addons.bldrs.app_cfgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*;
import gplx.core.strings.*;
public class Xoac_wiki_cfg_bldr_cmd {
public Xoac_wiki_cfg_bldr_cmd(String key, String text) {this.key = key; this.text = text;}

@ -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.cfgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.bldrs.*;
package gplx.xowa.addons.bldrs.app_cfgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*;
public class Xoac_wiki_cfg_bldr_fil implements Gfo_invk {
public Xoac_wiki_cfg_bldr_fil(String wiki) {this.wiki = wiki;}
public String Wiki() {return wiki;} private String wiki;

@ -15,8 +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.bldrs.cfgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.bldrs.*;
package gplx.xowa.addons.bldrs.app_cfgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*;
import gplx.core.strings.*;
import gplx.xowa.bldrs.*;
public class Xob_wiki_cfg_bldr implements Gfo_invk {
public Xob_wiki_cfg_bldr(Xob_bldr bldr) {this.app = bldr.App();} private Xoae_app app;
public void Exec() {

@ -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.cfgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.bldrs.*;
package gplx.xowa.addons.bldrs.app_cfgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*;
import org.junit.*; import gplx.core.strings.*;
public class Xob_wiki_cfg_bldr_tst {
Xob_wiki_cfg_bldr_fxt fxt = new Xob_wiki_cfg_bldr_fxt();

@ -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.bldrs.app_cfgs.wm_server_cfgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*; import gplx.xowa.addons.bldrs.app_cfgs.*;
import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.wkrs.*;
public class Xowm_server_cfg_cmd extends Xob_cmd__base {
public Xowm_server_cfg_cmd(Xob_bldr bldr, Xowe_wiki wiki) {super(bldr, wiki);}
@Override public void Cmd_run() {
// wiki.Init_assert();
// mgr.Exec(wiki);
}
public static final String BLDR_CMD_KEY = "cfg.wikis.wm_server_cfg";
@Override public String Cmd_key() {return BLDR_CMD_KEY;}
public static final Xob_cmd Prototype = new Xowm_server_cfg_cmd(null, null);
@Override public Xob_cmd Cmd_clone(Xob_bldr bldr, Xowe_wiki wiki) {return new Xowm_server_cfg_cmd(bldr, wiki);}
}

@ -0,0 +1,36 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.bldrs.app_cfgs.wm_server_cfgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*; import gplx.xowa.addons.bldrs.app_cfgs.*;
import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.wkrs.*;
public class Xowm_server_cfg_mgr {
public void Exec() {
byte[] src = Load_or_download();
Parse_cat_collation(src);
}
private byte[] Load_or_download() {
// Io_mgr.Instance.DownloadFil_args("", Io_url_.NullPtr).Exec_as_bry("https://noc.wikimedia.org/conf/InitialiseSettings.php.txt");
return null;
}
private void Parse_cat_collation(byte[] src) {
int bgn_pos = Bry_find_.Find_fwd(src, Bry_.new_a7("wgCategoryCollation"));
if (bgn_pos == Bry_find_.Not_found) throw Err_.new_wo_type("could not find wgCategoryCollation bgn");
int end_pos = Bry_find_.Find_fwd(src, Bry_.new_a7("],"));
if (end_pos == Bry_find_.Not_found) throw Err_.new_wo_type("could not find wgCategoryCollation end");
Tfds.Write(src, bgn_pos, end_pos);
}
}

@ -54,4 +54,8 @@ public class Xobc_data_db {
tbl__import_step.Delete(step_id);
}
}
public static Xobc_data_db New(gplx.xowa.apps.fsys.Xoa_fsys_mgr fsys_mgr) {
return new Xobc_data_db(fsys_mgr.Bin_addon_dir().GenSubFil_nest("bldr", "central", "bldr_central.data_db.xowa"));
}
}

@ -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.bldrs.centrals.dbs.datas; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*; import gplx.xowa.addons.bldrs.centrals.*; import gplx.xowa.addons.bldrs.centrals.dbs.*;
public class Xobc_task_regy_itm {
public Xobc_task_regy_itm(int id, int seqn, byte[] key, byte[] name, int step_count) {
this.id = id;
this.seqn = seqn;
this.key = key;
this.name = name;
this.step_count = step_count;
}
public int Id() {return id;} private final int id;
public int Seqn() {return seqn;} private final int seqn;
public byte[] Key() {return key;} private final byte[] key;
public byte[] Name() {return name;} private final byte[] name;
public int Step_count() {return step_count;} private final int step_count;
}

@ -67,6 +67,28 @@ public class Xobc_task_regy_tbl implements Db_tbl {
.Val_str(fld_task_key, task_key).Val_str(fld_task_name, task_name)
.Exec_insert();
}
public Xobc_task_regy_itm[] Select_by_wiki(byte[] wiki_domain) {
String sql = Db_sql_.Make_by_fmt(String_.Ary
( "SELECT *"
, "FROM task_regy"
, "WHERE task_key LIKE '{0}%'"
, "AND task_seqn != 999999"
), wiki_domain);
List_adp list = List_adp_.New();
Db_rdr rdr = conn.Stmt_sql(sql).Exec_select__rls_auto();
try {
while (rdr.Move_next()) {
list.Add(new Xobc_task_regy_itm
( rdr.Read_int("task_id")
, rdr.Read_int("task_seqn")
, rdr.Read_bry_by_str("task_key")
, rdr.Read_bry_by_str("task_name")
, rdr.Read_int("step_count")
));
}
} finally {rdr.Rls();}
return (Xobc_task_regy_itm[])list.To_ary_and_clear(Xobc_task_regy_itm.class);
}
public void Delete(int task_id) {
conn.Stmt_delete(tbl_name, fld_task_id).Crt_int(fld_task_id, task_id).Exec_delete();
}

@ -44,20 +44,7 @@ public class Xobc_import_step_tbl implements Db_tbl {
Db_rdr rdr = conn.Stmt_select(tbl_name, flds, fld_step_id).Crt_int(fld_step_id, step_id).Exec_select__rls_auto();
try {
return (rdr.Move_next())
? new Xobc_import_step_itm
( rdr.Read_int(fld_step_id)
, rdr.Read_int(fld_host_id)
, rdr.Read_bry_by_str(fld_wiki_abrv)
, rdr.Read_str(fld_wiki_date)
, rdr.Read_str(fld_import_name)
, rdr.Read_int(fld_import_type)
, rdr.Read_byte(fld_import_zip)
, rdr.Read_long(fld_import_size_zip)
, rdr.Read_long(fld_import_size_raw)
, rdr.Read_str(fld_import_md5)
, rdr.Read_long(fld_prog_size_end)
, rdr.Read_int(fld_prog_count_end)
)
? New_itm(rdr)
: Xobc_import_step_itm.Null;
}
finally {rdr.Rls();}
@ -95,7 +82,39 @@ public class Xobc_import_step_tbl implements Db_tbl {
}
} finally {rdr.Rls();}
}
public Xobc_import_step_itm[] Select_by_task_id(int task_id) {
List_adp list = List_adp_.New();
Db_rdr rdr = conn.Stmt_sql(Db_sql_.Make_by_fmt(String_.Ary
( "SELECT s.*"
, "FROM import_step s"
, " JOIN step_map sm ON s.step_id = sm.step_id"
, "WHERE sm.task_id = {0}"
), task_id))
.Exec_select__rls_auto();
try {
while (rdr.Move_next()) {
list.Add(New_itm(rdr));
}
} finally {rdr.Rls();}
return (Xobc_import_step_itm[])list.To_ary_and_clear(Xobc_import_step_itm.class);
}
public void Rls() {
insert_stmt = Db_stmt_.Rls(insert_stmt);
}
private Xobc_import_step_itm New_itm(Db_rdr rdr) {
return new Xobc_import_step_itm
( rdr.Read_int(fld_step_id)
, rdr.Read_int(fld_host_id)
, rdr.Read_bry_by_str(fld_wiki_abrv)
, rdr.Read_str(fld_wiki_date)
, rdr.Read_str(fld_import_name)
, rdr.Read_int(fld_import_type)
, rdr.Read_byte(fld_import_zip)
, rdr.Read_long(fld_import_size_zip)
, rdr.Read_long(fld_import_size_raw)
, rdr.Read_str(fld_import_md5)
, rdr.Read_long(fld_prog_size_end)
, rdr.Read_int(fld_prog_count_end)
);
}
}

@ -19,7 +19,7 @@ package gplx.xowa.addons.bldrs.exports.packs.files; import gplx.*; import gplx.x
import gplx.core.progs.*; import gplx.core.ios.zips.*; import gplx.core.ios.streams.*; import gplx.core.security.*;
import gplx.dbs.*; import gplx.xowa.wikis.data.*; import gplx.fsdb.*; import gplx.fsdb.meta.*;
import gplx.xowa.addons.bldrs.centrals.dbs.*; import gplx.xowa.addons.bldrs.centrals.dbs.datas.*; import gplx.xowa.addons.bldrs.centrals.dbs.datas.imports.*; import gplx.xowa.addons.bldrs.centrals.steps.*; import gplx.xowa.addons.bldrs.centrals.hosts.*;
class Pack_file_mgr {
public class Pack_file_mgr {
public void Exec(Xowe_wiki wiki, Pack_file_bldr_cfg cfg) {
// init
wiki.Init_assert();
@ -31,7 +31,7 @@ class Pack_file_mgr {
// get import_tbl
byte[] wiki_abrv = wiki.Domain_itm().Abrv_xo();
Xobc_data_db bc_db = new Xobc_data_db(wiki.App().Fsys_mgr().Bin_addon_dir().GenSubFil_nest("bldr", "central", "bldr_central.data_db.xowa"));
Xobc_data_db bc_db = Xobc_data_db.New(wiki.App().Fsys_mgr());
Db_conn bc_conn = bc_db.Conn();
bc_db.Delete_by_import(wiki_abrv, wiki_date);
bc_conn.Txn_bgn("xobc_import_insert");
@ -93,7 +93,7 @@ class Pack_file_mgr {
int pack_list_len = pack_list.Len();
// create task
String task_key = wiki.Domain_str() + "|" + wiki_date + "|" + task_type;
String task_key = Task_key__build(wiki.Domain_str(), wiki_date, task_type);
String task_name = Build_task_name(tmp_bfr, wiki, wiki_date, task_type, raw_len);
Xobc_task_regy_tbl task_regy_tbl = bc_db.Tbl__task_regy();
int task_id = bc_db.Conn().Sys_mgr().Autonum_next("task_regy.task_id");
@ -161,6 +161,12 @@ class Pack_file_mgr {
bc_db.Tbl__step_regy().Insert(step_id, Xobc_step_itm.Type__wiki_import);
bc_db.Tbl__import_step().Insert(step_id, gplx.xowa.addons.bldrs.centrals.dbs.datas.Xobc_host_regy_tbl.Host_id__archive_org, wiki_abrv, wiki_date, zip_url.NameAndExt(), itm.Tid(), Xobc_zip_type.Type__zip, zip_md5, zip_len, raw_size, 0, 0);
}
private static String Task_key__build(String wiki_domain, String wiki_date, String task_type) {
return String_.Concat(wiki_domain, "|", wiki_date, "|", task_type);
}
public static String[] Task_key__parse(String task_key) {
return String_.Split(task_key, "|");
}
}
class Pack_hash_bldr {
public static Pack_hash Bld(Xow_wiki wiki, Io_url wiki_dir, Io_url pack_dir, String wiki_date, boolean pack_html, boolean pack_file, DateAdp pack_file_cutoff, boolean pack_fsdb_delete) {

@ -33,7 +33,7 @@ class Pack_mgr {
// get import_tbl
byte[] wiki_abrv = wiki.Domain_itm().Abrv_xo();
Xobc_data_db bc_db = new Xobc_data_db(wiki.App().Fsys_mgr().Bin_addon_dir().GenSubFil_nest("bldr", "central", "bldr_central.data_db.xowa"));
Xobc_data_db bc_db = Xobc_data_db.New(wiki.App().Fsys_mgr());
Db_conn bc_conn = bc_db.Conn();
bc_db.Delete_by_import(wiki_abrv, wiki_date);
bc_conn.Txn_bgn("xobc_import_insert");

@ -19,6 +19,8 @@ package gplx.xowa.addons.bldrs.files; import gplx.*; import gplx.xowa.*; import
import gplx.xowa.bldrs.wkrs.*;
import gplx.xowa.addons.bldrs.files.cmds.*;
import gplx.xowa.addons.bldrs.mass_parses.inits.*; import gplx.xowa.addons.bldrs.mass_parses.parses.*; import gplx.xowa.addons.bldrs.mass_parses.makes.*;
import gplx.xowa.addons.bldrs.files.cksums.*;
import gplx.xowa.addons.bldrs.app_cfgs.wm_server_cfgs.*;
public class Xoax_builds_files_addon implements Xoax_addon_itm, Xoax_addon_itm__bldr {
public Xob_cmd[] Bldr_cmds() {
return new Xob_cmd[]
@ -43,6 +45,9 @@ public class Xoax_builds_files_addon implements Xoax_addon_itm, Xoax_addon_itm__
, Xomp_init_cmd.Prototype
, Xomp_parse_cmd.Prototype
, Xomp_make_cmd.Prototype
, Xocksum_calc_cmd.Prototype
, Xowm_server_cfg_cmd.Prototype
};
}

@ -0,0 +1,30 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.bldrs.files.cksums; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*; import gplx.xowa.addons.bldrs.files.*;
import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.wkrs.*;
public class Xocksum_calc_cmd extends Xob_cmd__base {
public Xocksum_calc_cmd(Xob_bldr bldr, Xowe_wiki wiki) {super(bldr, wiki);}
@Override public void Cmd_run() {
wiki.Init_assert();
new Xocksum_calc_mgr().Exec(wiki);
}
@Override public String Cmd_key() {return BLDR_CMD_KEY;} private static final String BLDR_CMD_KEY = "fsdb.cksums.calc";
public static final Xob_cmd Prototype = new Xocksum_calc_cmd(null, null);
@Override public Xob_cmd Cmd_clone(Xob_bldr bldr, Xowe_wiki wiki) {return new Xocksum_calc_cmd(bldr, wiki);}
}

@ -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.bldrs.files.cksums; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*; import gplx.xowa.addons.bldrs.files.*;
import gplx.core.ios.streams.*; import gplx.core.security.*;
import gplx.dbs.*; import gplx.xowa.addons.bldrs.files.cksums.dbs.*;
import gplx.xowa.files.*; import gplx.fsdb.*; import gplx.fsdb.data.*;
public class Xocksum_calc_mgr {
public void Exec(Xowe_wiki wiki) {
// get conn variables
Xocksum_cksum_db db = Xocksum_cksum_db.Get(wiki);
Db_conn conn = db.Conn();
Xocksum_cksum_tbl tbl = db.Tbl__cksum();
conn.Meta_tbl_assert(tbl);
// insert missing items
tbl.Insert_missing();
tbl.Create_idx();
// get updates
int count = 0;
Hash_algo md5_algo = Hash_algo_.New__md5();
List_adp updates = List_adp_.New();
String cur_date = Datetime_now.Get().XtoStr_gplx();
Db_stmt select_stmt = tbl.Select_samples_stmt(10000);
while (true) {
// get cksum_rows
Xocksum_cksum_row[] rows = tbl.Select_samples(select_stmt);
// loop cksum_rows and (a) get bin_data; (b) if md5 diff, then add to updates
int len = rows.length; if (len == 0) break;
for (int i = 0; i < len; ++i) {
Xocksum_cksum_row row = rows[i];
byte[] bin_bry = Get_bin(wiki, row);
if (bin_bry == null) {
Gfo_usr_dlg_.Instance.Prog_many("", "", "null; fil_id=~{0} thm_id=~{1}", row.Fil_id(), row.Thm_id());
bin_bry = Bry_.Empty;
}
row.Bin_size_(bin_bry.length);
byte[] md5 = md5_algo.Hash_bry_as_bry(bin_bry);
if (!Bry_.Eq(md5, row.Cksum_val())) {
row.Cksum_val_(md5);
updates.Add(row);
}
}
// run updates
conn.Txn_bgn("cksum_update");
len = updates.Len();
for (int i = 0; i < len; ++i) {
Xocksum_cksum_row row = (Xocksum_cksum_row)updates.Get_at(i);
tbl.Update(row.Fil_id(), row.Thm_id(), row.Bin_db_id(), row.Bin_size(), row.Cksum_tid(), 0, row.Cksum_val(), cur_date);
if (++count % 2000 == 0) Gfo_usr_dlg_.Instance.Prog_many("", "", "updating; rows=~{0}", count);
}
updates.Clear();
conn.Txn_end();
}
select_stmt.Rls();
}
private byte[] Get_bin(Xowe_wiki wiki, Xocksum_cksum_row row) {
int bin_id = row.Thm_id() == -1 ? row.Fil_id() : row.Thm_id();
Fsd_bin_itm bin_itm = wiki.File__mnt_mgr().Mnts__get_main().Bin_mgr().Dbs__get_at(row.Bin_db_id()).Select_as_itm(bin_id);
return bin_itm.Bin_data();
}
}

@ -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.bldrs.files.cksums.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*; import gplx.xowa.addons.bldrs.files.*; import gplx.xowa.addons.bldrs.files.cksums.*;
import gplx.dbs.*; import gplx.fsdb.meta.*;
public class Xocksum_cksum_db {
public Xocksum_cksum_db(Db_conn conn) {
this.conn = conn;
this.tbl__cksum = new Xocksum_cksum_tbl(conn);
}
public Db_conn Conn() {return conn;} private final Db_conn conn;
public Xocksum_cksum_tbl Tbl__cksum() {return tbl__cksum;} private final Xocksum_cksum_tbl tbl__cksum;
public static Xocksum_cksum_db Get(Xowe_wiki wiki) {
return new Xocksum_cksum_db(wiki.File__fsdb_core().File__abc_file__at(Fsm_mnt_mgr.Mnt_idx_main).Conn());
}
}

@ -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.bldrs.files.cksums.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*; import gplx.xowa.addons.bldrs.files.*; import gplx.xowa.addons.bldrs.files.cksums.*;
public class Xocksum_cksum_row {
public Xocksum_cksum_row(int fil_id, int thm_id, int bin_db_id, long bin_size, byte cksum_tid, int cksum_count, byte[] cksum_val, String cksum_date) {
this.fil_id = fil_id;
this.thm_id = thm_id;
this.bin_db_id = bin_db_id;
this.bin_size = bin_size;
this.cksum_tid = cksum_tid;
this.cksum_count = cksum_count;
this.cksum_val = cksum_val;
this.cksum_date = cksum_date;
}
public int Fil_id() {return fil_id;} private final int fil_id;
public int Thm_id() {return thm_id;} private final int thm_id;
public int Bin_db_id() {return bin_db_id;} private final int bin_db_id;
public long Bin_size() {return bin_size;} private long bin_size;
public byte Cksum_tid() {return cksum_tid;} private final byte cksum_tid;
public int Cksum_count() {return cksum_count;} private final int cksum_count;
public byte[] Cksum_val() {return cksum_val;} private byte[] cksum_val;
public String Cksum_date() {return cksum_date;} private final String cksum_date;
public void Bin_size_(long v) {this.bin_size = v;}
public void Cksum_val_(byte[] v) {this.cksum_val = v;}
}

@ -0,0 +1,107 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.bldrs.files.cksums.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.bldrs.*; import gplx.xowa.addons.bldrs.files.*; import gplx.xowa.addons.bldrs.files.cksums.*;
import gplx.dbs.*; import gplx.dbs.qrys.*; import gplx.xowa.addons.wikis.ctgs.*;
public class Xocksum_cksum_tbl implements Db_tbl {
private final Dbmeta_fld_list flds = new Dbmeta_fld_list();
private final String fld__fil_id, fld__thm_id, fld__bin_db_id, fld__bin_len, fld__cksum_tid, fld__cksum_count, fld__cksum_val, fld__cksum_date;
private Db_stmt stmt__update;
public Xocksum_cksum_tbl(Db_conn conn) {
this.conn = conn;
this.tbl_name = "fsdb_cksum";
this.fld__fil_id = flds.Add_int("fil_id");
this.fld__thm_id = flds.Add_int("thm_id");
this.fld__bin_db_id = flds.Add_int("bin_db_id");
this.fld__bin_len = flds.Add_long("bin_size");
this.fld__cksum_tid = flds.Add_byte("cksum_tid");
this.fld__cksum_count = flds.Add_int("cksum_count");
this.fld__cksum_val = flds.Add_str("cksum_val", 255);
this.fld__cksum_date = flds.Add_str("cksum_date", 16);
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() {
conn.Meta_idx_create(Dbmeta_idx_itm.new_normal_by_tbl(tbl_name, "fil_id__thm_id", fld__fil_id, fld__thm_id));
conn.Meta_idx_create(Dbmeta_idx_itm.new_normal_by_tbl(tbl_name, fld__cksum_val, fld__cksum_val));
}
public void Insert_missing() {
// insert from fsdb_fil
conn.Exec_sql(Db_sql_.Make_by_fmt(String_.Ary
( "INSERT INTO fsdb_cksum (fil_id, thm_id, bin_db_id, bin_size, cksum_tid, cksum_count, cksum_val, cksum_date)"
, "SELECT f.fil_id, -1, f.fil_bin_db_id, f.fil_size, {0}, 0, '', ''"
, "FROM fsdb_fil f"
, " LEFT JOIN fsdb_cksum c ON c.fil_id = f.fil_id AND c.thm_id = -1"
, "WHERE c.fil_id IS NULL"
, "AND f.fil_bin_db_id != -1"
), Cksum_tid__md5));
// insert from fsdb_fil
conn.Exec_sql(Db_sql_.Make_by_fmt(String_.Ary
( "INSERT INTO fsdb_cksum (fil_id, thm_id, bin_db_id, bin_size, cksum_tid, cksum_count, cksum_val, cksum_date)"
, "SELECT t.thm_owner_id, t.thm_id, t.thm_bin_db_id, t.thm_size, {0}, 0, '', ''"
, "FROM fsdb_thm t"
, " LEFT JOIN fsdb_cksum c ON c.fil_id = t.thm_owner_id AND c.thm_id = t.thm_id"
, "WHERE c.fil_id IS NULL"
), Cksum_tid__md5));
}
public Db_stmt Select_samples_stmt(int count) {
return conn.Stmt_sql(Db_sql_.Make_by_fmt(String_.Ary
( "SELECT *"
, "FROM fsdb_cksum"
, "WHERE cksum_val = ''"
// , "ORDER BY cksum_count, cksum_date"
, "LIMIT {0}"
), count));
}
public Xocksum_cksum_row[] Select_samples(Db_stmt stmt) {
List_adp rv = List_adp_.New();
Db_rdr rdr = stmt.Exec_select__rls_manual();
try {
while (rdr.Move_next()) {
rv.Add(new Xocksum_cksum_row
( rdr.Read_int("fil_id")
, rdr.Read_int("thm_id")
, rdr.Read_int("bin_db_id")
, rdr.Read_long("bin_size")
, rdr.Read_byte("cksum_tid")
, rdr.Read_int("cksum_count")
, rdr.Read_bry_by_str("cksum_val")
, rdr.Read_str("cksum_date")
));
}
} finally {rdr.Rls();}
return (Xocksum_cksum_row[])rv.To_ary_and_clear(Xocksum_cksum_row.class);
}
public void Update(int fil_id, int thm_id, int bin_db_id, long bin_size, byte cksum_tid, int cksum_count, byte[] cksum_val, String cksum_date) {
if (stmt__update == null) stmt__update = conn.Stmt_update_exclude(tbl_name, flds, fld__fil_id, fld__thm_id);
stmt__update.Clear()
.Val_int(fld__bin_db_id, bin_db_id).Val_long(fld__bin_len, bin_size)
.Val_byte(fld__cksum_tid, cksum_tid).Val_int(fld__cksum_count, cksum_count)
.Val_bry_as_str(fld__cksum_val, cksum_val).Val_str(fld__cksum_date, cksum_date)
.Crt_int(fld__fil_id, fil_id).Crt_int(fld__thm_id, thm_id)
.Exec_update();
}
public void Rls() {
this.stmt__update = Db_stmt_.Rls(stmt__update);
}
public static final byte Cksum_tid__md5 = 1;
}

@ -39,7 +39,7 @@ class Hdump_html_loader {
html_db.Tbl__html().Select_by_page(tmp_hpg);
// unzip it
byte[] html_hzip = stream_zip_mgr.Unzip(Io_stream_.Tid_gzip, tmp_hpg.Db().Html().Html_bry());
byte[] html_hzip = stream_zip_mgr.Unzip(Io_stream_tid_.Tid__gzip, tmp_hpg.Db().Html().Html_bry());
return wiki.Html__hdump_mgr().Load_mgr().Decode_as_bry(tmp_bfr, tmp_hpg, html_hzip, true);
}
}

@ -31,7 +31,7 @@ public class Xomp_parse_mgr_cfg implements Gfo_invk {
public boolean Log_file_lnkis() {return log_file_lnkis;} private boolean log_file_lnkis = true;
public boolean Load_all_templates() {return load_all_templates;} private boolean load_all_templates = true;
public boolean Load_all_imglnks() {return load_all_imglnks;} private boolean load_all_imglnks = true;
public byte Zip_tid() {return zip_tid;} private byte zip_tid = Io_stream_.Tid_gzip;
public byte Zip_tid() {return zip_tid;} private byte zip_tid = Io_stream_tid_.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;

@ -32,7 +32,7 @@ class Xodel_make_mgr {
, "FROM xfer_regy xr"
, "WHERE xr.lnki_ttl = fsdb_regy.fsdb_name"
, "AND xr.file_is_orig = fsdb_regy.fsdb_is_orig"
, "AND xr.orig_repo = fsdb_regy.fsdb_repo"
// , "AND xr.orig_repo = fsdb_regy.fsdb_repo" // TOMBSTONE: do no reinstate; some images exist in both repos, and this will delete images from one repo; DATE:2016-09-28
, "AND xr.file_w = fsdb_regy.fsdb_w"
, "AND xr.lnki_time = fsdb_regy.fsdb_time"
, "AND xr.lnki_page = fsdb_regy.fsdb_page"

@ -0,0 +1,59 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.htmls.includes; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.htmls.*;
import java.io.FileReader;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
class Script_engine__java implements Script_engine {
private final ScriptEngine engine;
private final Invocable invk;
public Script_engine__java() {
ScriptEngineManager manager = new ScriptEngineManager();
this.engine = manager.getEngineByName("JavaScript");
this.invk = (Invocable)engine;
}
public void Load_script(Io_url url) {
try {
engine.eval(new FileReader(url.Xto_api()));
// return engine.eval(script);
} catch (Exception e) {
System.out.println(e);
}
}
public void Put_object(String key, Object val) {
engine.put(key, val);
}
public Object Get_object(String obj_name) {
try {
return engine.get(obj_name);
} catch (Exception e) {
System.out.println(e);
return null;
}
}
public Object Invoke_method(Object obj, String func, Object... args) {
try {
return invk.invokeMethod(obj, func, args);
} catch (Exception e) {
System.out.println(e);
return null;
}
}
}

@ -0,0 +1,30 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.htmls.includes; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.htmls.*;
interface Script_engine {
void Load_script(Io_url url);
Object Get_object(String obj_name);
void Put_object(String name, Object obj);
Object Invoke_method(Object obj, String func, Object... args);
}
class Script_engine__noop implements Script_engine {
public void Load_script(Io_url url) {}
public Object Get_object(String obj_name) {return null;}
public void Put_object(String name, Object obj) {}
public Object Invoke_method(Object obj, String func, Object... args) {return null;}
}

@ -0,0 +1,57 @@
/*
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.includes; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.htmls.*;
import gplx.xowa.wikis.pages.tags.*;
public class Xoh_include_mgr {
private Io_url[] main_urls; private int main_urls_len;
public void Init(Xow_wiki wiki) {
// check bin dir
Io_url include_dir = wiki.Fsys_mgr().Root_dir().GenSubDir_nest("bin", "html", "include");
if (!Io_mgr.Instance.ExistsDir(include_dir)) return;
this.main_urls = Io_mgr.Instance.QueryDir_args(include_dir).FilPath_("*.js").ExecAsUrlAry();
this.main_urls_len = main_urls.length;
if (main_urls_len == 0) {
Gfo_usr_dlg_.Instance.Warn_many("", "", "no '.js' files found; dir=~{0}", include_dir.Raw());
return;
}
}
public void Write(Xow_wiki wiki, Xoa_page page) {
this.Init(wiki);
if (main_urls_len == 0) return;
// create engine and load scripts
Script_engine engine = new Script_engine__java();
for (int i = 0; i < main_urls_len; ++i) {
engine.Load_script(main_urls[i]);
}
// engine.Put_object("page", new Xoscript_page())
Xoscript_page xos_pg = new Xoscript_page();
Object xowa_script = engine.Get_object("xowa_script");
// engine.Invoke_method(xowa_script, "main", page.Url().To_str());
engine.Invoke_method(xowa_script, "main", xos_pg);
// if (String_.Has(rv, "yes")) {
// Io_url js_url = null;
// page.Html_data().Custom_head_tags().Add(Xopg_tag_itm.New_js_file(js_url));
// }
}
// public static Xoh_include_mgr Get_or_new(Xow_wiki wiki) {
// wiki.Addon_mgr().Itms__get_or_null();
// }
}

@ -0,0 +1,24 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.addons.htmls.includes; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.htmls.*;
public class Xoscript_page {
private Xoscript_page_doc doc = new Xoscript_page_doc();
public Xoscript_page_doc Doc() {
return doc;
}
}

@ -0,0 +1,23 @@
/*
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.includes; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.htmls.*;
public class Xoscript_page_doc {
public void Test() {
Tfds.Write("hi");
}
}

@ -19,12 +19,10 @@ package gplx.xowa.addons.wikis.ctgs.bldrs; import gplx.*; import gplx.xowa.*; im
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;
@ -42,17 +40,13 @@ class Xob_catlink_mgr {
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
// sortkey
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();
if (collation_id != Xoctg_collation_enum.Tid__uca) {
// sortkey; handle \n
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
}
// insert to tmp; notify; commit
@ -76,12 +70,12 @@ class Xob_catlink_mgr {
}
// create tbl
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);
// 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
// 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();
@ -92,7 +86,7 @@ class Xob_catlink_mgr {
wkr.Update_page_cat_db_id(wiki, page_conn);
// cleanup
cat_sort_tbl.Delete_idx__key(); // remove idx
// cat_sort_tbl.Delete_idx__key(); // remove idx
tmp_db.Delete();
}
}

@ -26,16 +26,16 @@ class Xob_catlink_wkr {
( "SELECT tcl.cl_from"
, ", p.page_id"
, ", tcl.cl_type_id"
, ", cs.cs_id"
, ", tcl.cl_timestamp"
, ", tcl.cl_sortkey"
, ", tcl.cl_sortkey_prefix"
, "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"
, " 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
// select from tmp_db and 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 {
@ -46,7 +46,9 @@ class Xob_catlink_wkr {
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
byte[] sortkey = rdr.Read_bry("cl_sortkey");
byte[] sortkey_prefix = rdr.Read_bry_by_str("cl_sortkey_prefix");
long db_size_new = db_size_cur + 48 + (sortkey.length * 2) + sortkey_prefix.length;// 46 = 3 ints (12) + 1 long (8) + 1 byte (2?) + 2 index (24?) + 11 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);
@ -56,7 +58,7 @@ class Xob_catlink_wkr {
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"));
cat_link_tbl.Insert_cmd_by_batch(page_id_prv, rdr.Read_int("page_id"), rdr.Read_byte("cl_type_id"), rdr.Read_long("cl_timestamp"), sortkey, sortkey_prefix);
if (++rows % 100000 == 0)
Gfo_usr_dlg_.Instance.Prog_many("", "", "inserting cat_link row: ~{0}", Int_.To_str_fmt(rows, "#,##0"));
}
@ -82,8 +84,8 @@ class Xob_catlink_wkr {
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();
cat_link_tbl.Create_idx__catbox();
cat_link_tbl.Create_idx__catpage();
}
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));

@ -1,45 +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.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();
@Test public void Basic() {
Uca_trie_fxt fxt = new Uca_trie_fxt();
fxt.Clear();
fxt.Init_trie_itm("a", Bry_.New_by_ints(10, 11));
fxt.Init_trie_itm("b", Bry_.New_by_ints(20, 21));
fxt.Init_trie_itm("c", Bry_.New_by_ints(30, 31));
fxt.Test_decode(Bry_.New_by_ints(10, 11), "a");
fxt.Test_decode(Bry_.New_by_ints(10, 11, 20, 21, 30, 31), "abc");
}
}
class Uca_trie_fxt {
public void Clear() {
if (trie == null) {
trie = new Uca_trie();
bfr = Bry_bfr_.New();
}
trie.Clear();
} Uca_trie trie; Bry_bfr bfr;
public void Init_trie_itm(String charAsStr, byte[] uca) {trie.Init_itm(gplx.core.intls.Utf16_.Decode_to_int(Bry_.new_u8(charAsStr), 0), uca);}
public void Test_decode(byte[] bry, String expd) {
trie.Decode(bfr, bry, 0, bry.length);
Tfds.Eq(expd, bfr.To_str_and_clear());
}
}

@ -20,32 +20,34 @@ 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 final String fld__from, fld__to_id, fld__type_id, fld__timestamp_unix, fld__sortkey, fld__sortkey_prefix;
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");
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__timestamp_unix = flds.Add_long ("cl_timestamp_unix");
this.fld__sortkey = flds.Add_bry ("cl_sortkey");
this.fld__sortkey_prefix = flds.Add_str ("cl_sortkey_prefix", 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__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 Create_idx__catbox() {conn.Meta_idx_create(Dbmeta_idx_itm.new_normal_by_tbl(tbl_name, "catbox", fld__from));}
public void Create_idx__catpage() {conn.Meta_idx_create(Dbmeta_idx_itm.new_normal_by_tbl(tbl_name, "catpage", fld__to_id, fld__type_id, fld__sortkey));}
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) {
public void Insert_cmd_by_batch(int from, int to_id, byte type_id, long timestamp_unix, byte[] sortkey, byte[] sortkey_prefix) {
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)
.Val_int(fld__from , from)
.Val_int(fld__to_id , to_id)
.Val_byte(fld__type_id , type_id)
.Val_long(fld__timestamp_unix , timestamp_unix)
.Val_bry(fld__sortkey , sortkey)
.Val_bry_as_str(fld__sortkey_prefix , sortkey_prefix)
.Exec_insert();
}
public void Rls() {

@ -26,7 +26,7 @@ public class Xodb_tmp_cat_link_tbl implements Db_tbl {
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_sortkey = flds.Add_bry ("cl_sortkey");
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");
@ -43,7 +43,7 @@ public class Xodb_tmp_cat_link_tbl implements Db_tbl {
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_bry(fld_sortkey , sortkey)
.Val_long(fld_timestamp , timestamp)
.Val_bry_as_str(fld_sortkey_prefix , sortkey_prefix)
.Val_byte(fld_collation_id , collation_id)

@ -17,14 +17,21 @@ 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.langs.*; import gplx.xowa.langs.msgs.*; import gplx.xowa.htmls.core.htmls.*; import gplx.core.intls.ucas.*;
import gplx.xowa.wikis.nss.*;
import gplx.xowa.addons.wikis.ctgs.htmls.catpages.doms.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.fmts.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.utls.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.urls.*;
public class Xoctg_catpage_mgr {
import gplx.xowa.addons.wikis.ctgs.htmls.catpages.doms.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.fmts.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.dbs.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.urls.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.langs.*;
public class Xoctg_catpage_mgr implements Gfo_invk {
private final Xow_wiki wiki;
private final Hash_adp_bry cache = Hash_adp_bry.cs();
private final Xoctg_catpage_loader loader = new Xoctg_catpage_loader();
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();
private final Uca_ltr_extractor ltr_extractor = new Uca_ltr_extractor(true);
public int Grp_max() {return grp_max;} private int grp_max = Grp_max_dflt;
public Xoctg_catpage_mgr(Xow_wiki wiki) {
this.wiki = wiki;
this.collation_mgr = new Xoctg_collation_mgr(wiki);
}
public Xoctg_collation_mgr Collation_mgr() {return collation_mgr;} private Xoctg_collation_mgr collation_mgr;
public Xoctg_fmt_grp Fmt(byte tid) {
switch (tid) {
case Xoa_ctg_mgr.Tid__subc: return fmt_subcs;
@ -34,32 +41,33 @@ public class Xoctg_catpage_mgr {
}
}
public void Free_mem_all() {cache.Clear();}
public Xoctg_catpage_ctg Get_or_load_or_null(Xow_wiki wiki, Xoa_ttl cat_ttl) {
public Xoctg_catpage_ctg Get_or_load_or_null(Xoctg_catpage_url catpage_url, Xoa_ttl cat_ttl, int limit) {
// load categories from cat dbs; exit if not found
Xoctg_catpage_ctg ctg = (Xoctg_catpage_ctg)cache.Get_by(cat_ttl.Full_db());
if (ctg == null) {
if (gplx.core.envs.Env_.Mode_testing()) return null; // needed for dpl test
ctg = loader.Load_by_ttl_or_null(wiki, cat_ttl);
synchronized (thread_lock) { // LOCK:used by multiple wrks; DATE:2016-09-12
ctg = loader.Load_ctg_or_null(wiki, this, catpage_url, cat_ttl, limit);
}
if (ctg == null) return null; // not in cache or db; exit
cache.Add(cat_ttl.Full_db(), ctg);
// cache.Add(cat_ttl.Full_db(), ctg);
}
return ctg;
}
public void Write_catpage(Bry_bfr bfr, Xow_wiki wiki, Xoa_page page, Xoh_wtr_ctx hctx) {
public void Write_catpage(Bry_bfr bfr, Xoa_page page, Xoh_wtr_ctx hctx) {
try {
// get catpage_url
Xoctg_catpage_url catpage_url = Xoctg_catpage_url_parser.Parse(page.Url());
// load categories from cat dbs; exit if not found
Xoctg_catpage_ctg ctg = Get_or_load_or_null(wiki, page.Ttl());
Xoctg_catpage_ctg ctg = Get_or_load_or_null(catpage_url, page.Ttl(), grp_max);
if (ctg == null) return;
// filter subs; need for large categories like de.w:Category:Mann
Xoctg_catpage_url catpage_url = Xoctg_catpage_url_parser.Parse(page.Url());
Xoctg_catpage_filter.Filter(grp_max, catpage_url, ctg);
// write html
Xol_lang_itm lang = page.Lang();
fmt_subcs.Write_catpage_grp(bfr, wiki, lang, ctg, grp_max);
fmt_pages.Write_catpage_grp(bfr, wiki, lang, ctg, grp_max);
fmt_files.Write_catpage_grp(bfr, wiki, lang, ctg, grp_max);
fmt_subcs.Write_catpage_grp(bfr, wiki, lang, ltr_extractor, ctg, grp_max);
fmt_pages.Write_catpage_grp(bfr, wiki, lang, ltr_extractor, ctg, grp_max);
fmt_files.Write_catpage_grp(bfr, wiki, lang, ltr_extractor, ctg, grp_max);
}
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));
@ -70,5 +78,12 @@ public class Xoctg_catpage_mgr {
cache.Add(ttl, ctg);
}
public void Grp_max_(int v) {grp_max = v;} // TEST:
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk__collation_)) collation_mgr.Collation_name_(m.ReadStr("v"));
else return Gfo_invk_.Rv_unhandled;
return this;
} private static final String Invk__collation_ = "collation_";
public static int Grp_max_dflt = 200;
private static final Object thread_lock = new Object();
}

@ -16,25 +16,27 @@ 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 org.junit.*; import gplx.xowa.htmls.core.htmls.*;
import org.junit.*; import gplx.xowa.htmls.core.htmls.*; import gplx.core.intls.ucas.*;
import gplx.xowa.addons.wikis.ctgs.htmls.catpages.doms.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.fmts.*;
public class Xoctg_catpage_mgr__basic__tst {
@Before public void init() {fxt.Clear();} private Xoctg_catpage_mgr_fxt fxt = new Xoctg_catpage_mgr_fxt();
@Test public void Page_itm() {
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__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_itms__pages("A1");
fxt .Ctg().Grp_by_tid(Xoa_ctg_mgr.Tid__page).Itms__get_at(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>");
fxt.Init_itms__pages("A1");
Xoctg_catpage_itm itm = fxt.Ctg().Grp_by_tid(Xoa_ctg_mgr.Tid__page).Itms__get_at(0);
itm.Page_ttl_(Xoa_ttl.Null);
itm.Sortkey_handle_make(Bry_bfr_.New(), Bry_.Empty);
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>");
}
@Test public void Visited_doesnt_work_for_space() {// PURPOSE: xowa-visited not inserted for pages with space
byte[] page_bry = Bry_.new_a7("A 1");
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_itms__pages("A_1").Init_grp__pages(0, 1)
fxt .Init_itms__pages("A_1")
.Test__html__all(Xoa_ctg_mgr.Tid__page, String_.Concat_lines_nl_skip_last
( ""
, "<div id=\"mw-pages\">"
@ -46,7 +48,7 @@ public class Xoctg_catpage_mgr__basic__tst {
, " <td style=\"width: 33%;\">"
, " <h3>A</h3>"
, " <ul>"
, " <li><a href=\"/wiki/A_1\" class=\"xowa-visited\" title=\"A 1\">A 1</a></li>"
, " <li><a href=\"/wiki/A_1\" class=\"xowa-visited\" title=\"A 1\">A 1</a><!----></li>"
, " </ul>"
, " </td>"
, " </tr>"
@ -56,7 +58,7 @@ public class Xoctg_catpage_mgr__basic__tst {
));
}
@Test public void Page_all() {
fxt .Init_itms__pages("A1").Init_grp__pages(0, 1)
fxt .Init_itms__pages("A1")
.Test__html__all(Xoa_ctg_mgr.Tid__page, String_.Concat_lines_nl_skip_last
( ""
, "<div id=\"mw-pages\">"
@ -68,7 +70,7 @@ public class Xoctg_catpage_mgr__basic__tst {
, " <td style=\"width: 33%;\">"
, " <h3>A</h3>"
, " <ul>"
, " <li><a href=\"/wiki/A1\" title=\"A1\">A1</a></li>"
, " <li><a href=\"/wiki/A1\" title=\"A1\">A1</a><!----></li>"
, " </ul>"
, " </td>"
, " </tr>"
@ -78,7 +80,7 @@ public class Xoctg_catpage_mgr__basic__tst {
));
}
@Test public void File_all() {
fxt .Init_itms__files("File:A1.png").Init_grp__files(0, 1)
fxt .Init_itms__files("File:A1.png")
.Test__html__all(Xoa_ctg_mgr.Tid__file, String_.Concat_lines_nl_skip_last
( ""
, "<div id=\"mw-category-media\">"
@ -90,7 +92,7 @@ public class Xoctg_catpage_mgr__basic__tst {
, " <td style=\"width: 33%;\">"
, " <h3>A</h3>"
, " <ul>"
, " <li><a href=\"/wiki/File:A1.png\" title=\"File:A1.png\">File:A1.png</a></li>"
, " <li><a href=\"/wiki/File:A1.png\" title=\"File:A1.png\">File:A1.png</a><!----></li>"
, " </ul>"
, " </td>"
, " </tr>"
@ -98,25 +100,9 @@ public class Xoctg_catpage_mgr__basic__tst {
, " </div>"
, "</div>"
));
// , " <ul id=\"xowa_gallery_ul_0\" class=\"gallery\">"
// , " <li class=\"gallerybox\" style=\"width:155px;\">"
// , " <div style=\"width:155px;\">"
// , " <div class=\"thumb\" style=\"width:155px;\">"
// , " <div id=\"xowa_gallery_div3_-1\" style=\"margin:15px auto;\">"
// , " <a href=\"/wiki/File:A1.png\" class=\"image\">"
// , " <img id=\"xoimg_-1\" alt=\"A1.png\" src=\"\" width=\"-1\" height=\"-1\" />"
// , " </a>"
// , " </div>"
// , " </div>"
// , " <div class=\"gallerytext\">A1.png"
// , " </div>"
// , " </div>"
// , " </li>"
// , ""
// , " </ul>"
}
@Test public void Subc_all() {
fxt .Init_itms__subcs("Category:Subc_1").Init_grp__files(0, 1)
fxt .Init_itms__subcs("Category:Subc_1")
.Test__html__all(Xoa_ctg_mgr.Tid__subc, String_.Concat_lines_nl_skip_last
( ""
, "<div id=\"mw-subcategories\">"
@ -152,46 +138,82 @@ public class Xoctg_catpage_mgr__basic__tst {
));
}
@Test public void Page_all_cols() {
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 5 total.</p>"
, " <div lang=\"en\" dir=\"ltr\" class=\"mw-content-ltr\">"
, " <table style=\"width: 100%;\">"
, " <tr style=\"vertical-align: top;\">"
, " <td style=\"width: 33%;\">"
, " <h3>A</h3>"
, " <ul>"
, " <li><a href=\"/wiki/A1\" title=\"A1\">A1</a></li>"
, " <li><a href=\"/wiki/A2\" title=\"A2\">A2</a></li>"
, " </ul>"
, " </td>"
, " <td style=\"width: 33%;\">"
, " <h3>A cont.</h3>"
, " <ul>"
, " <li><a href=\"/wiki/A3\" title=\"A3\">A3</a></li>"
, " </ul>"
, " <h3>B</h3>"
, " <ul>"
, " <li><a href=\"/wiki/B1\" title=\"B1\">B1</a></li>"
, " </ul>"
, " </td>"
, " <td style=\"width: 33%;\">"
, " <h3>C</h3>"
, " <ul>"
, " <li><a href=\"/wiki/C1\" title=\"C1\">C1</a></li>"
, " </ul>"
, " </td>"
, " </tr>"
, " </table>"
, " </div>"
, "</div>"
));
fxt.Init_itms__pages("A1", "A2", "A3", "B1", "C1");
fxt.Init__grp_max_(6);
fxt.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 5 total.</p>"
, " <div lang=\"en\" dir=\"ltr\" class=\"mw-content-ltr\">"
, " <table style=\"width: 100%;\">"
, " <tr style=\"vertical-align: top;\">"
, " <td style=\"width: 33%;\">"
, " <h3>A</h3>"
, " <ul>"
, " <li><a href=\"/wiki/A1\" title=\"A1\">A1</a><!----></li>"
, " <li><a href=\"/wiki/A2\" title=\"A2\">A2</a><!----></li>"
, " </ul>"
, " </td>"
, " <td style=\"width: 33%;\">"
, " <h3>A cont.</h3>"
, " <ul>"
, " <li><a href=\"/wiki/A3\" title=\"A3\">A3</a><!----></li>"
, " </ul>"
, " <h3>B</h3>"
, " <ul>"
, " <li><a href=\"/wiki/B1\" title=\"B1\">B1</a><!----></li>"
, " </ul>"
, " </td>"
, " <td style=\"width: 33%;\">"
, " <h3>C</h3>"
, " <ul>"
, " <li><a href=\"/wiki/C1\" title=\"C1\">C1</a><!----></li>"
, " </ul>"
, " </td>"
, " </tr>"
, " </table>"
, " </div>"
, "</div>"
));
}
@Test public void Page__numeric() { // PURPOSE: check numeric sorting; 0, 9, 10; not 0, 10, 9; DATE:2016-10-09
fxt.Init_itms__pages("0", "9", "10");
fxt.Init__grp_max_(6);
fxt.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 3 pages are in this category, out of 3 total.</p>"
, " <div lang=\"en\" dir=\"ltr\" class=\"mw-content-ltr\">"
, " <table style=\"width: 100%;\">"
, " <tr style=\"vertical-align: top;\">"
, " <td style=\"width: 33%;\">"
, " <h3>0-9</h3>"
, " <ul>"
, " <li><a href=\"/wiki/0\" title=\"0\">0</a><!----></li>"
, " </ul>"
, " </td>"
, " <td style=\"width: 33%;\">"
, " <h3>0-9 cont.</h3>"
, " <ul>"
, " <li><a href=\"/wiki/9\" title=\"9\">9</a><!----></li>"
, " </ul>"
, " </td>"
, " <td style=\"width: 33%;\">"
, " <h3>0-9 cont.</h3>"
, " <ul>"
, " <li><a href=\"/wiki/10\" title=\"10\">10</a><!----></li>"
, " </ul>"
, " </td>"
, " </tr>"
, " </table>"
, " </div>"
, "</div>"
));
}
@Test public void Title__escape_quotes() {// PURPOSE: quotes in title should be escaped; DATE:2015-12-28
fxt .Init_itms__pages("A\"1").Init_grp__pages(0, 1)
fxt .Init_itms__pages("A\"1")
.Test__html__all(Xoa_ctg_mgr.Tid__page, String_.Concat_lines_nl_skip_last
( ""
, "<div id=\"mw-pages\">"
@ -203,7 +225,7 @@ public class Xoctg_catpage_mgr__basic__tst {
, " <td style=\"width: 33%;\">"
, " <h3>A</h3>"
, " <ul>"
, " <li><a href=\"/wiki/A%221\" title=\"A&quot;1\">A&quot;1</a></li>"
, " <li><a href=\"/wiki/A%221\" title=\"A&quot;1\">A&quot;1</a><!----></li>"
, " </ul>"
, " </td>"
, " </tr>"
@ -226,44 +248,49 @@ public class Xoctg_catpage_mgr__basic__tst {
}
class Xoctg_catpage_mgr_fxt {
private int grp_max;
private Uca_ltr_extractor ltr_extractor = new Uca_ltr_extractor(true);
public Xoctg_catpage_mgr_fxt Clear() {
if (app == null) {
app = Xoa_app_fxt.Make__app__edit();
wiki = Xoa_app_fxt.Make__wiki__edit(app);
ctg_html = wiki.Html_mgr().Catpage_mgr();
ctg_html = wiki.Ctg__catpage_mgr();
}
ctg = new Xoctg_catpage_ctg(Bry_.new_a7("Ctg_1"));
grp_max = Xoctg_catpage_mgr.Grp_max_dflt;
ctg = new Xoctg_catpage_ctg(1, Bry_.new_a7("Ctg_1"));
grp_max = 3; // default to 3 paer page
return this;
} 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_catpage_ctg Ctg() {return ctg;} private Xoctg_catpage_ctg ctg;
public void Init__grp_max_(int v) {this.grp_max = v;}
public void Init__prev_hide_y_(byte tid) {ctg.Grp_by_tid(tid).Prev_disable_(true);}
public void Init__next_sortkey_(byte tid, String v) {ctg.Grp_by_tid(tid).Next_sortkey_(Bry_.new_u8(v));}
public void Test__navlink(boolean next, String ctg_str, String expd) {
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), grp_max);
Tfds.Eq_str_lines(expd, String_.new_u8(actl));
}
public Xoctg_catpage_mgr_fxt Init_grp_max(int v) {this.grp_max = v; return this;}
public Xoctg_catpage_mgr_fxt Init_grp__pages(int bgn, int count) {ctg.Pages().Rng_(bgn, count); return this;}
public Xoctg_catpage_mgr_fxt Init_grp__files(int bgn, int count) {ctg.Files().Rng_(bgn, count); return this;}
public Xoctg_catpage_mgr_fxt Init_itms__pages(String... titles) {return Init_itms(Xoa_ctg_mgr.Tid__page, titles);}
public Xoctg_catpage_mgr_fxt Init_itms__files(String... titles) {return Init_itms(Xoa_ctg_mgr.Tid__file, titles);}
public Xoctg_catpage_mgr_fxt Init_itms__subcs(String... titles) {return Init_itms(Xoa_ctg_mgr.Tid__subc, titles);}
private Xoctg_catpage_mgr_fxt Init_itms(byte tid, String[] ttls) {
int len = ttls.length;
Xoctg_catpage_tmp tmp = new Xoctg_catpage_tmp();
Xoctg_catpage_grp grp = ctg.Grp_by_tid(tid);
grp.Count_all_(len);
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()));
byte[] page_ttl_bry = Bry_.new_u8(ttls[i]);
Xoa_ttl ttl = Xoa_ttl.Parse(wiki, page_ttl_bry);
Xoctg_catpage_itm itm = Xoctg_catpage_itm.New_by_ttl(tid, i, ttl);
tmp.Add(itm);
}
grp.Itms__make();
tmp.Make_by_grp(grp);
return this;
}
public void Test__html__page(byte tid, byte grp_char_0, String expd) {
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.Init_from_ltr(wiki, list, ltr_extractor);
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();
@ -273,14 +300,14 @@ class Xoctg_catpage_mgr_fxt {
public void Test__html_grp(byte tid, String expd) {
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));
fmtr_grp.Init_from_grp(wiki, ctg.Grp_by_tid(tid), ltr_extractor);
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.Fmt(tid).Write_catpage_grp(bfr, wiki, wiki.Lang(), ctg, grp_max);
ctg_html.Fmt(tid).Write_catpage_grp(bfr, wiki, wiki.Lang(), ltr_extractor, ctg, grp_max);
Tfds.Eq_str_lines(expd, bfr.To_str_and_rls());
}
}

@ -21,43 +21,39 @@ import gplx.xowa.addons.wikis.ctgs.htmls.catpages.doms.*; import gplx.xowa.addon
public class Xoctg_catpage_mgr__navlink__tst {
@Before public void init() {fxt.Clear();} private Xoctg_catpage_mgr_fxt fxt = new Xoctg_catpage_mgr_fxt();
@Test public void Navlink__basic() {
fxt .Init_itms__pages("A1", "A2", "A3").Init_grp_max(1).Init_grp__pages(1, 2)
.Test__navlink(Bool_.Y, "Category:Ctg_1", String_.Concat_lines_nl
fxt.Init_itms__pages("A2", "A3", "A4");
fxt.Init__next_sortkey_(Xoa_ctg_mgr.Tid__page, "A5");
fxt.Test__navlink(Bool_.Y, "Category:Ctg_1", String_.Concat_lines_nl
( ""
, "(<a href=\"/wiki/Category:Ctg_1?pageuntil=A2#mw-pages\" class=\"xowa_nav\" title=\"Category:Ctg_1\">previous 1</a>)"
, "(<a href=\"/wiki/Category:Ctg_1?pagefrom=A3#mw-pages\" class=\"xowa_nav\" title=\"Category:Ctg_1\">next 1</a>)"
, "(<a href=\"/wiki/Category:Ctg_1?pageuntil=A2%0AA2#mw-pages\" class=\"xowa_nav\" title=\"Category:Ctg_1\">previous 3</a>)"
, "(<a href=\"/wiki/Category:Ctg_1?pagefrom=A5#mw-pages\" class=\"xowa_nav\" title=\"Category:Ctg_1\">next 3</a>)"
));
}
@Test public void Navlink__encoded() { // escape quotes and spaces; DATE:2016-01-11
fxt .Init_itms__pages("A\" 1", "A\" 2", "A\" 3").Init_grp_max(1).Init_grp__pages(1, 2)
.Test__navlink(Bool_.Y, "Category:Ctg_1", String_.Concat_lines_nl
fxt.Init_itms__pages("A\" 2", "A\" 3", "A\" 4");
fxt.Init__next_sortkey_(Xoa_ctg_mgr.Tid__page, "A\" 5");
fxt.Test__navlink(Bool_.Y, "Category:Ctg_1", String_.Concat_lines_nl
( ""
, "(<a href=\"/wiki/Category:Ctg_1?pageuntil=A%22+2#mw-pages\" class=\"xowa_nav\" title=\"Category:Ctg_1\">previous 1</a>)"
, "(<a href=\"/wiki/Category:Ctg_1?pagefrom=A%22+3#mw-pages\" class=\"xowa_nav\" title=\"Category:Ctg_1\">next 1</a>)"
, "(<a href=\"/wiki/Category:Ctg_1?pageuntil=A%22+2%0AA%22+2#mw-pages\" class=\"xowa_nav\" title=\"Category:Ctg_1\">previous 3</a>)"
, "(<a href=\"/wiki/Category:Ctg_1?pagefrom=A%22+5#mw-pages\" class=\"xowa_nav\" title=\"Category:Ctg_1\">next 3</a>)"
));
}
@Test public void Navlink__bos() {
fxt .Init_itms__pages("A1", "A2", "A3").Init_grp_max(1).Init_grp__pages(0, 1)
.Test__navlink(Bool_.Y, "Category:Ctg_1", String_.Concat_lines_nl
fxt.Init_itms__pages("A2", "A3", "A4");
fxt.Init__prev_hide_y_(Xoa_ctg_mgr.Tid__page);
fxt.Init__next_sortkey_(Xoa_ctg_mgr.Tid__page, "A5");
fxt.Test__navlink(Bool_.Y, "Category:Ctg_1", String_.Concat_lines_nl
( ""
, "(previous 1)"
, "(<a href=\"/wiki/Category:Ctg_1?pagefrom=A2#mw-pages\" class=\"xowa_nav\" title=\"Category:Ctg_1\">next 1</a>)"
, "(previous 3)"
, "(<a href=\"/wiki/Category:Ctg_1?pagefrom=A5#mw-pages\" class=\"xowa_nav\" title=\"Category:Ctg_1\">next 3</a>)"
));
}
@Test public void Navlink__eos() {
fxt .Init_itms__pages("A1", "A2", "A3").Init_grp_max(2).Init_grp__pages(2, 3)
.Test__navlink(Bool_.Y, "Category:Ctg_1", String_.Concat_lines_nl
fxt.Init_itms__pages("A2", "A3", "A4");
fxt.Test__navlink(Bool_.Y, "Category:Ctg_1", String_.Concat_lines_nl
( ""
, "(<a href=\"/wiki/Category:Ctg_1?pageuntil=A3#mw-pages\" class=\"xowa_nav\" title=\"Category:Ctg_1\">previous 2</a>)"
, "(next 2)"
));
}
@Test public void Navlink__eos__2() { // PURPOSE.fix: do not suppress next page on penultimate page; DATE:2016-09-25
fxt .Init_itms__pages("A1", "A2", "A3", "A4").Init_grp_max(2).Init_grp__pages(2, 3)
.Test__navlink(Bool_.Y, "Category:Ctg_1", String_.Concat_lines_nl
( ""
, "(<a href=\"/wiki/Category:Ctg_1?pageuntil=A3#mw-pages\" class=\"xowa_nav\" title=\"Category:Ctg_1\">previous 2</a>)"
, "(<a href=\"/wiki/Category:Ctg_1?pagefrom=A4#mw-pages\" class=\"xowa_nav\" title=\"Category:Ctg_1\">next 2</a>)"
, "(<a href=\"/wiki/Category:Ctg_1?pageuntil=A2%0AA2#mw-pages\" class=\"xowa_nav\" title=\"Category:Ctg_1\">previous 3</a>)"
, "(next 3)"
));
}
}

@ -0,0 +1,182 @@
/*
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.dbs; 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.dbs.*; import gplx.xowa.wikis.data.*; import gplx.xowa.wikis.data.tbls.*;
import gplx.xowa.addons.wikis.ctgs.htmls.catpages.doms.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.langs.*;
class Xoctg_catlink_loader {
private byte version;
private int link_dbs_len;
private Db_attach_mgr attach_mgr;
private final Bry_bfr sortkey_val_bfr = Bry_bfr_.New();
public void Run(Xoctg_catpage_ctg rv, Xow_wiki wiki, Xoctg_catpage_mgr catpage_mgr, Xowd_page_tbl page_tbl, int cat_id, byte grp_tid, boolean url_is_from, byte[] url_sortkey, int limit) {
String sql = Bld_sql(catpage_mgr, cat_id, grp_tid, url_is_from, url_sortkey, limit);
Load_catlinks(rv, wiki, page_tbl, rv.Grp_by_tid(grp_tid), sql, url_is_from, limit);
}
public void Make_attach_mgr__v2(Xow_db_mgr db_mgr, int cat_link_db_idx) {
this.version = 2;
this.link_dbs_len = 1;
Xow_db_file cat_link_db = db_mgr.Dbs__get_by_id_or_fail(cat_link_db_idx);
this.attach_mgr = new Db_attach_mgr(cat_link_db.Conn(), new Db_attach_itm("link_db_1", cat_link_db.Conn()));
}
public void Make_attach_mgr__v3_v4(Xow_db_mgr db_mgr, Db_conn cat_core_conn) {
// init db vars
List_adp db_list = List_adp_.New();
Db_conn db_1st = null;
int db_idx = 0;
// fill db_list by looping over each db unless (a) cat_link_db or (b) core_db (if all or few)
int len = db_mgr.Dbs__len();
for (int i = 0; i < len; ++i) {
Xow_db_file cl_db = db_mgr.Dbs__get_at(i);
switch (cl_db.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: // skip all other files
continue;
}
// add to db_list
if (db_1st == null) db_1st = cl_db.Conn();
db_list.Add(new Db_attach_itm("link_db_" + ++db_idx, cl_db.Conn()));
}
// make attach_mgr
this.version = 4;
this.link_dbs_len = db_list.Len();
if (cat_core_conn.Meta_tbl_exists("cat_sort")) {
version = 3;
db_1st = cat_core_conn;
}
this.attach_mgr = new Db_attach_mgr(db_1st, (Db_attach_itm[])db_list.To_ary_and_clear(Db_attach_itm.class));
}
private String Bld_sql (Xoctg_catpage_mgr catpage_mgr, int cat_id, byte grp_tid, boolean url_is_from, byte[] url_sortkey, int limit) {
Bry_bfr bfr = Bry_bfr_.New();
for (int i = 0; i < link_dbs_len; ++i)
Bld_sql_by_db(catpage_mgr, cat_id, grp_tid, url_is_from, url_sortkey, i + List_adp_.Base1, bfr);
bfr.Add_str_u8_fmt
( "\nORDER BY cl_to_id, cl_type_id, cl_sortkey {0}"
+ "\nLIMIT {1}"
, url_is_from ? "ASC" : "DESC", limit + 1);
return bfr.To_str_and_clear();
}
private void Bld_sql_by_db (Xoctg_catpage_mgr catpage_mgr, int cat_id, byte grp_tid, boolean url_is_from, byte[] url_sortkey, int link_db_id, Bry_bfr bfr) {
if (link_db_id != List_adp_.Base1) bfr.Add_str_a7("\nUNION\n");
// change sortkey vars per version; note that v3 differs from v2 and v4 b/c of cat_sort tbl
String sortkey_col = "cl_sortkey";
String sortkey_join = "";
if (version == 3) { // NOTE: version 3 takes sortkey from cat_sort
sortkey_col = "cs.cs_key";
sortkey_join = "\n JOIN cat_sort cs ON cl.cl_sortkey_id = cs.cs_id";
}
// sortkey_val
byte[] sortkey_val = null;
String sortkey_prefix_fld = version == 4 ? "cl_sortkey_prefix" : "''";
sortkey_val = Build_sortkey_val(sortkey_val_bfr, version, catpage_mgr.Collation_mgr(), url_sortkey);
// bld sql; NOTE: building sql with args embedded b/c (a) UNION requires multiple Crt_arg for each ?; (EX: 4 unions, 3 ? require 12 .Crt_arg); (b) easier to debug
String sql = Db_sql_.Make_by_fmt(String_.Ary
( "SELECT cl_to_id"
, ", cl_from"
, ", cl_type_id"
, ", {3} AS cl_sortkey"
, ", {7} AS cl_sortkey_prefix"
, "FROM <link_db_{0}>cat_link cl{6}"
, "WHERE cl_to_id = {1}"
, "AND cl_type_id = {2}"
, "AND {3} {4} {5}"
), link_db_id, cat_id, grp_tid, sortkey_col, url_is_from ? ">=" : "<", sortkey_val, sortkey_join, sortkey_prefix_fld);
bfr.Add_str_u8(sql);
}
private void Load_catlinks(Xoctg_catpage_ctg rv, Xow_wiki wiki, Xowd_page_tbl page_tbl, Xoctg_catpage_grp grp, String sql, boolean url_is_from, int limit) {
// init; prep sql
Xoctg_page_loader catlink_loader = new Xoctg_page_loader(wiki);
Ordered_hash hash = catlink_loader.Hash();
sql = attach_mgr.Resolve_sql(sql);
// run sql and create itms based on cat_link
Xoctg_catpage_itm itm_zth = null;
Db_rdr rdr = Db_rdr_.Empty;
int row_idx = 0;
try {
attach_mgr.Attach();
rdr = attach_mgr.Conn_main().Stmt_sql(sql).Exec_select__rls_auto();
while (rdr.Move_next()) {
Xoctg_catpage_itm itm = Xoctg_catpage_itm.New_by_rdr(rdr, version);
if (row_idx++ < limit) // row_idx >= limit for last row; EX: 200 < 200
hash.Add(itm.Page_id(), itm);
else { // last row; EX: 201
if (url_is_from) // from=some_key; 201st row is sort_key for "(Next 200)"
itm_zth = itm;
else // until=some_key; 201st row means that 200th row is not 1st row; show prev link
grp.Prev_disable_(false);
}
}
}
finally {
rdr.Rls();
attach_mgr.Detach();
}
// load ns / ttl from page
page_tbl.Select_in__id(catlink_loader);
grp.Itms_((Xoctg_catpage_itm[])hash.To_ary_and_clear(Xoctg_catpage_itm.class));
// set data for Next 200 / Previous 200
if (itm_zth != null) {
if (version == 4) {
Xowd_page_itm tmp_pg = new Xowd_page_itm();
page_tbl.Select_by_id(tmp_pg, itm_zth.Page_id());
Xoa_ttl zth_ttl = wiki.Ttl_parse(tmp_pg.Ns_id(), tmp_pg.Ttl_page_db());
itm_zth.Page_ttl_(zth_ttl);
itm_zth.Sortkey_handle_make(Bry_bfr_.New(), grp.Itms__get_at(grp.Itms__len() - 1).Sortkey_handle());
grp.Next_sortkey_(itm_zth.Sortkey_handle());
}
else
grp.Next_sortkey_(itm_zth.Sortkey_handle());
}
}
public static byte[] Build_sortkey_val(Bry_bfr sortkey_val_bfr, byte version, Xoctg_collation_mgr collation_mgr, byte[] url_sortkey) {
// find \n and ignore everything after it; needed else "< 'A\nA'" will pull up "A"; NOTE: can't find logic in MediaWiki CategoryViewer.php; DATE:2016-10-11
// ALSO: needed for v2 else SQL will literally have WHERE cl_sortkey = 'A\nA';
byte[] tmp_sortkey = url_sortkey;
int nl_pos = Bry_find_.Find_fwd(tmp_sortkey, Byte_ascii.Nl);
if (nl_pos != Bry_find_.Not_found)
tmp_sortkey = Bry_.Mid(tmp_sortkey, 0, nl_pos);
if (version == 4) {
if (Bry_.Len_gt_0(url_sortkey)) {
// make sortkey_val
sortkey_val_bfr.Add_byte(Byte_ascii.Ltr_x).Add_byte_apos();
gplx.core.encoders.Hex_utl_.Encode_bfr(sortkey_val_bfr, collation_mgr.Get_sortkey(tmp_sortkey));
sortkey_val_bfr.Add_byte_apos();
}
else
sortkey_val_bfr.Add_byte_apos().Add_byte_apos();
}
else
sortkey_val_bfr.Add_byte_apos().Add(Db_sql_.Escape_arg(tmp_sortkey)).Add_byte_apos();
return sortkey_val_bfr.To_bry_and_clear();
}
}

@ -0,0 +1,39 @@
/*
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.dbs; 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 org.junit.*; import gplx.core.tests.*; import gplx.xowa.apps.urls.*;
import gplx.xowa.langs.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.langs.*;
public class Xoctg_catlink_loader__tst {
private final Xoctg_catlink_loader__fxt fxt = new Xoctg_catlink_loader__fxt();
@Test public void Build_sortkey_val__v4() { // PURPOSE: remove "\n" and afterwards else will omit 1 record
fxt.Test__build_sortkey_sql(4, "A\nA", "x'41'"); // fails if "x'410a41'"
}
@Test public void Build_sortkey_val__v2() { // PURPOSE: remove "\n" and afterwards else SQL will be malformed
fxt.Test__build_sortkey_sql(2, "A\nA", "'A'"); // fails if "'A\nA'"
}
}
class Xoctg_catlink_loader__fxt {
public void Test__build_sortkey_sql(int version, String sortkey, String expd) {
Xoae_app app = Xoa_app_fxt.Make__app__edit();
Xowe_wiki wiki = Xoa_app_fxt.Make__wiki__edit(app, "de.wikipedia.org"); // use "de.wikipedia.org" for simple "uppercase" collation
Xoctg_collation_mgr collation_mgr = new Xoctg_collation_mgr(wiki);
Bry_bfr bfr = Bry_bfr_.New();
Gftest.Eq__str(expd, Xoctg_catlink_loader.Build_sortkey_val(bfr, Byte_.By_int(version), collation_mgr, Bry_.new_u8(sortkey)));
}
}

@ -0,0 +1,71 @@
/*
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.dbs; 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.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.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.urls.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.dbs.*;
public class Xoctg_catpage_loader {
public Xoctg_catpage_ctg Load_ctg_or_null(Xow_wiki wiki, Xoctg_catpage_mgr catpage_mgr, Xoctg_catpage_url cat_url, Xoa_ttl cat_ttl, int limit) {
// get cat_id 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;
}
int cat_id = page_itm.Id();
// get cat_core_itm from cat_core_tbl
Xowd_cat_core_tbl cat_core_tbl = Xodb_cat_db_.Get_cat_core_or_fail(db_mgr);
Xowd_category_itm cat_core_itm = cat_core_tbl.Select(cat_id);
if (cat_core_itm == Xowd_category_itm.Null) {
Gfo_usr_dlg_.Instance.Log_many("", "", "category does not exist in cat_core table; ttl=~{0}", cat_ttl.Full_db()); // NOTE: this is not rare as Category pages can be created as deliberately empty, or as redirects; fr.w:Catégorie:Utilisateur_hess-4; DATE:2016-09-12
return null;
}
// load itms from cat_link_db for each grp_tid
Xoctg_catpage_ctg rv = new Xoctg_catpage_ctg(cat_id, cat_ttl.Page_txt());
for (byte grp_tid = Xoa_ctg_mgr.Tid__subc; grp_tid < Xoa_ctg_mgr.Tid___max; ++grp_tid) {
Xoctg_catpage_grp grp = rv.Grp_by_tid(grp_tid);
grp.Count_all_(cat_core_itm.Count_by_tid(grp_tid)); // set total counts per grp based on cat_core_itm;
// init url_vars
boolean url_is_from = cat_url.Grp_fwds()[grp_tid]; // EX: "pagefrom=A"; "pageuntil=B"
byte[] url_sortkey = cat_url.Grp_keys()[grp_tid];
// set prev / next props to dflt values
if (url_is_from) { // url is from; EX: from=A
if (Bry_.Len_eq_0(url_sortkey)) // no sortkey specified for group, so group always starts with 1st itm -> disable previous link
grp.Prev_disable_(true);
}
else { // url is until; EX: until=A
grp.Prev_disable_(true); // default prev link to disabled; loader will load 201 items and set to false if 201st found
grp.Next_sortkey_(url_sortkey); // next sortkey is always sortkey of until url arg;
}
// load links
Xoctg_catlink_loader loader = new Xoctg_catlink_loader();
if (cat_core_itm.File_idx() == -1) // v3 or v4: loop over all cat_link dbs {
loader.Make_attach_mgr__v3_v4 (db_mgr, cat_core_tbl.Conn());
else // v2: use cat_link_db
loader.Make_attach_mgr__v2 (db_mgr, cat_core_itm.File_idx());
loader.Run(rv, wiki, catpage_mgr, page_tbl, cat_id, grp_tid, url_is_from, url_sortkey, limit);
}
return rv;
}
}

@ -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.catpages.dbs; 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.dbs.*; import gplx.xowa.wikis.data.tbls.*;
import gplx.xowa.addons.wikis.ctgs.htmls.catpages.doms.*;
public class Xoctg_page_loader implements Select_in_cbk {
private final Xow_wiki wiki;
private final Ordered_hash hash = Ordered_hash_.New();
public Xoctg_page_loader(Xow_wiki wiki) {this.wiki = wiki;}
public Ordered_hash Hash() {return hash;}
public int Hash_max() {return hash.Len();}
public void Write_sql(Bry_bfr bfr, int idx) {
Xoctg_catpage_itm itm = (Xoctg_catpage_itm)hash.Get_at(idx);
bfr.Add_int_variable(itm.Page_id());
}
public void Read_data(Db_rdr rdr) {
// read values from page_tbl
int page_id = rdr.Read_int("page_id");
int page_ns = rdr.Read_int("page_namespace");
byte[] page_ttl = rdr.Read_bry_by_str("page_title");
// get itm and set data
Xoctg_catpage_itm itm = (Xoctg_catpage_itm)hash.Get_by(page_id);
if (itm == null) return; // NOTE: itms can exist in cat_links_tbl, but not in page_tbl; EX:User:Any_page
itm.Page_ttl_(wiki.Ttl_parse(page_ns, page_ttl));
}
}

@ -17,12 +17,15 @@ 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.Itms__len() + pages.Itms__len() + files.Itms__len();}
public Xoctg_catpage_ctg(int id, byte[] name) {
this.id = id; this.name = name;
}
public int Id() {return id;} private final int id;
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.Count_all() + pages.Count_all() + files.Count_all();}
public Xoctg_catpage_grp Grp_by_tid(byte tid) {
switch (tid) {
case Xoa_ctg_mgr.Tid__subc: return subcs;
@ -31,10 +34,4 @@ public class Xoctg_catpage_ctg {
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();
}
}
}

@ -17,27 +17,38 @@ 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 {
private final List_adp tmp_list = List_adp_.New();
private Xoctg_catpage_itm[] itms = Xoctg_catpage_itm.Ary_empty;
private byte[] next_sortkey = Bry_.Empty;
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; // idx of 1st item; EX: 200
public int End() {return end;} private int end; // idx of nth item + 1; EX: 399
public int Count_by_page() {return end - bgn;} // count of items on page; EX: 200
public int Itms__len() {return itms_len;} private int itms_len; // count of items in entire category; EX: 456
public Xoctg_catpage_itm[] Itms() {return itms;} private Xoctg_catpage_itm[] itms = Xoctg_catpage_itm.Ary_empty;
public Xoctg_catpage_itm Itms__get_at(int i) {
if (i < 0 || i >= itms.length) throw Err_.new_wo_type("catpage: 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 byte Tid() {return tid;} private byte tid; // subc|page|file
public int Count_all() {return count_all;} private int count_all; // count of items in entire category; EX: 456
public boolean Prev_disable() {return prev_disable;} private boolean prev_disable; // prev_link: disable link
public byte[] Next_sortkey() {return next_sortkey;} // next_link: set sortkey
public int Itms__len() {return itms.length;}
public Xoctg_catpage_itm Itms__get_at(int i) {return itms[i];}
public void Count_all_(int v) {this.count_all = v;}
public void Prev_disable_(boolean v) {this.prev_disable = v;}
public void Next_sortkey_(byte[] v) {this.next_sortkey = v;}
public void Itms_(Xoctg_catpage_itm[] v) {
this.itms = v;
Array_.Sort(itms, new Xoctg_catpage_itm_sorter()); // NOTE: need to reorder for page_until b/c ORDER BY DESC
// make sortkey_handle
Bry_bfr tmp_bfr = Bry_bfr_.New();
int itms_len = itms.length;
byte[] prv_sortkey_handle = Bry_.Empty;
for (int i = 0; i < itms_len; ++i) {
Xoctg_catpage_itm itm = itms[i];
prv_sortkey_handle = itm.Sortkey_handle_make(tmp_bfr, prv_sortkey_handle);
}
}
public void Itms__add(Xoctg_catpage_itm sub) {tmp_list.Add(sub);}
public void Itms__make() {
tmp_list.Sort_by(Xoctg_catpage_itm_sorter__sort_key.Sorter);
itms = (Xoctg_catpage_itm[])tmp_list.To_ary_and_clear(Xoctg_catpage_itm.class);
bgn = 0;
end = itms_len = itms.length;
}
public void Rng_(int bgn, int end) {
this.bgn = bgn; this.end = end;
}
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.Sortkey_binary(), rhs.Sortkey_binary());
}
}

@ -16,17 +16,86 @@ 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.*;
import gplx.dbs.*; import gplx.xowa.wikis.nss.*;
public class Xoctg_catpage_itm {
public Xoctg_catpage_itm(int page_id, Xoa_ttl page_ttl, byte[] sort_key) {
private byte version;
Xoctg_catpage_itm(byte version, byte grp_tid, int page_id, byte[] sortkey_prefix, byte[] sortkey_binary) {
this.version = version;
this.grp_tid = grp_tid;
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
this.page_ttl = Xoa_ttl.Null;
this.sortkey_prefix = sortkey_prefix;
this.sortkey_handle = sortkey_prefix; // default handle to sortkey_prefix;
this.sortkey_binary = sortkey_binary;
}
public byte Grp_tid() {return grp_tid;} private final byte grp_tid; // v2-v4:cl_type_id; subc,page,file
public int Page_id() {return page_id;} private final int page_id; // v2-v4:cl_from
public byte[] Sortkey_prefix() {return sortkey_prefix;} private byte[] sortkey_prefix; // v2-v3:cl_sortkey; v4:cl_sortkey_prefix
public byte[] Sortkey_handle() {return sortkey_handle;} private byte[] sortkey_handle; // v2-v3:cl_sortkey; v4:cl_sortkey_prefix\nttl_txt; never "cl_sortkey" which is binary ICU value;
public byte[] Sortkey_binary() {return sortkey_binary;} private byte[] sortkey_binary; // v2-v4:cl_sortkey; note that v4 is binary icu value
public Xoa_ttl Page_ttl() {return page_ttl;} private Xoa_ttl page_ttl;
public void Page_ttl_(Xoa_ttl ttl) {
this.page_ttl = ttl;
// sortkey_prefix will be blank for v2; use page_ttl; PAGE:s.w:Category:Computer_science DATE:2015-11-22
if (version == Version__2 && Bry_.Len_eq_0(sortkey_prefix))
sortkey_prefix = page_ttl.Page_txt();
// sortkey_binary will be blank for v2,v3; use page_ttl; PAGE:fr.w:Article_contenant_un_appel_à_traduction_en_anglais; DATE:2016-10-11
if (version != Version__4 && Bry_.Len_eq_0(sortkey_binary)) sortkey_binary = page_ttl.Page_txt();
}
public byte[] Sortkey_handle_make(Bry_bfr tmp_bfr, byte[] prv_sortkey_handle) {
// page.tbl missing even though in cat_link.tbl; happens for "User:" namespace pages;
if (page_ttl == Xoa_ttl.Null) {
// sortkey_prefix exists; happens for [[Category:A]] as opposed to [[Category:A|some_sortkey_prefix]]
if (Bry_.Len_gt_0(sortkey_prefix)) {
sortkey_handle = sortkey_prefix;
return sortkey_handle; // set sortkey_prefix as new prv_sortkey_handle;
}
else {
// set sortkey_handle to "prv_sortkey" + "page_id"; needed for multiple "missing" catlinks which span 200 page boundaries
tmp_bfr.Add(prv_sortkey_handle);
tmp_bfr.Add_byte_nl();
tmp_bfr.Add_int_variable(page_id);
sortkey_handle = tmp_bfr.To_bry_and_clear();
return prv_sortkey_handle;
}
}
// page.tbl exists
else {
// "In UCA, tab is the only character that can sort above LF so we strip both of them from the original prefix."; Title.php|getCategorySortKey
if (sortkey_prefix.length == 0) {
sortkey_handle = page_ttl.Page_txt();
}
else {
byte[] sortkey_normalized = Bry_.Replace(sortkey_prefix, Sortkey_prefix_replace__src, Sortkey_prefix_replace__trg);
tmp_bfr.Add(sortkey_normalized);
tmp_bfr.Add_byte_nl().Add(page_ttl.Page_txt()); // "$prefix\n$unprefixed";
sortkey_handle = tmp_bfr.To_bry_and_clear();
}
return sortkey_handle;
}
}
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 static final Xoctg_catpage_itm[] Ary_empty = new Xoctg_catpage_itm[0];
public static Xoctg_catpage_itm New_by_rdr(Db_rdr rdr, byte version) {
byte[] sortkey_binary = Bry_.Empty;
byte[] sortkey_prefix = Bry_.Empty;
if (version == Version__4) {
sortkey_binary = rdr.Read_bry("cl_sortkey");
sortkey_prefix = rdr.Read_bry_by_str("cl_sortkey_prefix");
}
else {
sortkey_binary = Bry_.Empty;
sortkey_prefix = rdr.Read_bry_by_str("cl_sortkey");
}
return new Xoctg_catpage_itm(version, rdr.Read_byte("cl_type_id"), rdr.Read_int("cl_from"), sortkey_prefix, sortkey_binary);
}
public static Xoctg_catpage_itm New_by_ttl(byte grp_tid, int page_id, Xoa_ttl ttl) { // TEST
Xoctg_catpage_itm rv = new Xoctg_catpage_itm(Version__4, grp_tid, page_id, ttl.Page_txt(), Bry_.Empty);
rv.Page_ttl_(ttl);
return rv;
}
private static final byte Version__2 = 2, Version__4 = 4;
private static final byte[] Sortkey_prefix_replace__src = Bry_.new_a7("\n\t"), Sortkey_prefix_replace__trg = Bry_.new_a7(" ");
}

@ -16,15 +16,28 @@ 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_sorter__sort_key implements gplx.core.lists.ComparerAble, gplx.core.lists.binary_searches.Binary_comparer {
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 class Xoctg_catpage_tmp {
private final List_adp subc_list = List_adp_.New(), page_list = List_adp_.New(), file_list = List_adp_.New();
public void Add(Xoctg_catpage_itm itm) {
List_adp list = Get_by_tid(itm.Grp_tid());
list.Add(itm);
}
public int Compare_val_to_obj(Object val, Object obj) {
Xoctg_catpage_itm itm = (Xoctg_catpage_itm)obj;
return Bry_.Compare((byte[])val, itm.Sort_key());
public void Make_by_ctg(Xoctg_catpage_ctg ctg) { // TEST:
for (byte tid = 0; tid < Xoa_ctg_mgr.Tid___max; ++tid)
Make_by_grp(ctg.Grp_by_tid(tid));
}
public void Make_by_grp(Xoctg_catpage_grp grp) {
byte tid = grp.Tid();
List_adp list = Get_by_tid(tid);
if (list.Len() == 0) return;
grp.Itms_((Xoctg_catpage_itm[])list.To_ary_and_clear(Xoctg_catpage_itm.class));
}
private List_adp Get_by_tid(byte tid) {
switch (tid) {
case Xoa_ctg_mgr.Tid__subc: return subc_list;
case Xoa_ctg_mgr.Tid__page: return page_list;
case Xoa_ctg_mgr.Tid__file: return file_list;
default: throw Err_.new_unhandled_default(tid);
}
}
public static final Xoctg_catpage_itm_sorter__sort_key Sorter = new Xoctg_catpage_itm_sorter__sort_key();
}

@ -16,7 +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.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.langs.*; import gplx.xowa.langs.msgs.*; import gplx.xowa.htmls.core.htmls.*; import gplx.langs.htmls.encoders.*; import gplx.core.intls.ucas.*;
import gplx.xowa.wikis.nss.*;
import gplx.xowa.addons.wikis.ctgs.htmls.catpages.doms.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.urls.*;
public class Xoctg_fmt_grp { // subc|page|file
@ -32,47 +32,43 @@ public class Xoctg_fmt_grp { // subc|page|file
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, int grp_max) { // TEST:
public void Write_catpage_grp(Bry_bfr bfr, Xow_wiki wiki, Xol_lang_itm lang, Uca_ltr_extractor ltr_extractor, Xoctg_catpage_ctg dom_ctg, int grp_max) { // TEST:
Xoctg_catpage_grp dom_grp = dom_ctg.Grp_by_tid(tid);
if (dom_grp.Itms__len() == 0) return; // no items in grp; EX: 0 items in File
if (dom_grp.Count_all() == 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.Count_by_page(), dom_grp.Itms__len());
byte[] msg_stats_bry = msg_mgr.Val_by_id_args(msg_stats_id, dom_grp.Itms__len(), dom_grp.Count_all());
// 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, grp_max);
// init grp; write
itms_fmt.Init_from_grp(wiki, dom_grp);
itms_fmt.Init_from_grp(wiki, dom_grp, ltr_extractor);
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, int grp_max) { // TEST:
if (view_grp.Itms__len() < grp_max) return Bry_.Empty; // < 200; never show;
if (view_grp.Count_all() < grp_max) return Bry_.Empty; // < 200; never show;
Bry_bfr bfr = wiki.Utl__bfr_mkr().Get_k004();
Html_nav_bry(bfr, wiki, ttl, view_grp, grp_max, Bool_.N);
Html_nav_bry(bfr, wiki, ttl, view_grp, grp_max, 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 grp, int grp_max, boolean type_is_next) {
private void Html_nav_bry(Bry_bfr bfr, Xow_wiki wiki, Xoa_ttl ttl, Xoctg_catpage_grp grp, int grp_max, boolean url_is_from) {
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_next) {
if (url_is_from) {
arg_idx_lbl = url_arg_bgn;
// get next category after last one on page; needed for "Next 200 (href=Cat_201)"
int nxt_idx = grp.End();
if (nxt_idx == grp.Itms__len()) --nxt_idx; // if last item, then grp.End() does not exist; just use last one
arg_sortkey = grp.Itms__get_at(nxt_idx).Sort_key();
arg_sortkey = grp.Next_sortkey();
}
else {
arg_idx_lbl = url_arg_end;
arg_sortkey = grp.Itms__get_at(grp.Bgn()).Sort_key(); // use 1st item as sortkey for "until" args
arg_sortkey = grp.Itms__get_at(0).Sortkey_handle(); // use 1st item as sortkey for "until" args
}
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
@ -80,12 +76,12 @@ public class Xoctg_fmt_grp { // subc|page|file
byte[] nav_href = href_bfr.To_bry_and_rls();
// get nav_text
int nav_text_id = type_is_next ? Xol_msg_itm_.Id_next_results : Xol_msg_itm_.Id_prev_results;
int nav_text_id = url_is_from ? 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
// print text if 1st / zth page; else, print html
if ( ( type_is_next && grp.Bgn() + grp_max > grp.Itms__len())
|| (!type_is_next && grp.Bgn() - grp_max < 0)
if ( ( url_is_from && Bry_.Len_eq_0(grp.Next_sortkey()))
|| (!url_is_from && grp.Prev_disable())
)
Fmt__nav__text.Bld_many(bfr, nav_text);
else

@ -17,27 +17,32 @@ 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.langs.*; import gplx.xowa.langs.msgs.*; import gplx.core.intls.ucas.*;
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 Uca_ltr_extractor ltr_extractor;
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.Count_by_page(), col_idx, Cols_max);
this.col_end = col_bgn + Calc_col_len(grp.Itms__len(), col_idx, Cols_max);
}
public void Init_from_ltr(Xow_wiki wiki, Xoctg_catpage_grp grp, Uca_ltr_extractor ltr_extractor) {
this.wiki = wiki;
this.grp = grp;
this.ltr_extractor = ltr_extractor;
}
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 grp_end = grp.End();
int grp_end = grp.Itms__len();
// loop over itms;
for (int i = loop_bgn; i < grp_end; i++) {
@ -50,28 +55,30 @@ public abstract class Xoctg_fmt_itm_base implements gplx.core.brys.Bfr_arg {
// get sortkey
Xoctg_catpage_itm itm = grp.Itms__get_at(i);
byte[] itm_sortkey = itm.Sort_key();
byte[] itm_sortkey = itm.Sortkey_handle();
// reached end of ltr; exit
if (!Bry_.Has_at_bgn(itm_sortkey, ltr_cur, 0, itm_sortkey.length)) {
byte[] ltr_1st = ltr_extractor.Get_1st_ltr(itm_sortkey);
if (!Bry_.Has_at_bgn(ltr_1st, ltr_cur, 0, ltr_1st.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());
Xoa_ttl itm_ttl = itm.Page_ttl();
Bld_html(bfr, wiki, history_mgr, href_parser, itm, itm_ttl);
}
loop_end_idx = grp_end;
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);
if (ttl == Xoa_ttl.Null)
fmt_missing.Bld_many(bfr, itm.Page_id(), itm.Sortkey_handle());
else {
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"
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);
fmt_exists.Bld_many(bfr, itm_href, itm_atr_cls, itm_full_ttl, itm_full_ttl, gplx.core.encoders.Hex_utl_.Encode_bry(itm.Sortkey_binary()));
}
}
private static final Bry_fmt
@ -81,7 +88,7 @@ public abstract class Xoctg_fmt_itm_base implements gplx.core.brys.Bfr_arg {
)
, fmt_exists = Bry_fmt.Auto_nl_skip_last
( ""
, " <li><a href=\"~{itm_href}\"~{itm_atr_cls} title=\"~{itm_title}\">~{itm_text}</a></li>"
, " <li><a href=\"~{itm_href}\"~{itm_atr_cls} title=\"~{itm_title}\">~{itm_text}</a><!--~{itm_sortkey}--></li>"
)
;
public static final int Cols_max = 3;

@ -17,23 +17,25 @@ 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.*;
import gplx.xowa.langs.*; import gplx.xowa.langs.msgs.*; import gplx.core.intls.ucas.*;
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;
private Uca_ltr_extractor ltr_extractor;
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) {
public void Init_from_grp(Xow_wiki wiki, Xoctg_catpage_grp grp, Uca_ltr_extractor ltr_extractor) {
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);
this.ltr_extractor = ltr_extractor;
itm_fmt.Init_from_ltr(wiki, grp, ltr_extractor);
}
public void Bfr_arg__add(Bry_bfr bfr) {
int itm_idx = grp.Bgn(); // itm idx; EX: idx=201 in len=500
int itm_end = grp.End();
int itm_idx = 0;
int itm_end = grp.Itms__len();
int itms_len = itm_end - itm_idx; if (itms_len == 0) return; // no items; exit
int col_idx = 0; // col idx; EX: 3 cols; idx = 0, 1, 2
@ -45,8 +47,9 @@ public class Xoctg_fmt_ltr implements gplx.core.brys.Bfr_arg { // "A", "B", "C c
Xoctg_catpage_itm itm = grp.Itms__get_at(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[] itm_sortkey = itm.Sortkey_handle();
// byte[] ltr_cur = gplx.core.intls.Utf8_.Get_char_at_pos_as_bry(itm_sortkey, 0);
byte[] ltr_cur = ltr_extractor.Get_1st_ltr(itm_sortkey);
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"

@ -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.catpages.langs; 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.core.intls.ucas.*;
public class Xoctg_collation_mgr {
private final Xow_wiki wiki;
private Uca_collator collator;
private String collation_name = "uppercase"; // REF:https://noc.wikimedia.org/conf/InitialiseSettings.php.txt|wgCategoryCollation|default
public Xoctg_collation_mgr(Xow_wiki wiki) {
this.wiki = wiki;
if (String_.Eq(wiki.Domain_str(), "en.wikipedia.org"))
collation_name = "uca-default-kn";
}
public void Collation_name_(String v) {
this.collation_name = v;
}
public byte[] Get_sortkey(byte[] src) {
if (String_.Eq(collation_name, "uppercase")) {
return wiki.Lang().Case_mgr().Case_build_upper(src);
}
else {
if (collator == null) collator = Uca_collator_.New(collation_name, true);
return collator.Get_sortkey(String_.new_u8(src));
}
}
}

@ -20,4 +20,16 @@ public class Xoctg_catpage_url {
public Xoctg_catpage_url(byte[][] keys, boolean[] fwds) {this.keys = keys; this.fwds = fwds;}
public byte[][] Grp_keys() {return keys;} private final byte[][] keys;
public boolean[] Grp_fwds() {return fwds;} private final boolean[] fwds;
public static Xoctg_catpage_url New__blank() {
byte[][] keys = new byte[Xoa_ctg_mgr.Tid___max][];
boolean[] fwds = new boolean[Xoa_ctg_mgr.Tid___max];
// for blank url, all fwds are true; EX: "Category:A" -> keys {"", "", ""}, fwds {true, true, true}
for (int i = 0; i < Xoa_ctg_mgr.Tid___max; ++i) {
fwds[i] = Bool_.Y;
keys[i] = Bry_.Empty;
}
return new Xoctg_catpage_url(keys, fwds);
}
}

@ -21,15 +21,20 @@ import gplx.langs.htmls.encoders.*;
public class Xoctg_catpage_url_parser {
public static Xoctg_catpage_url Parse(Xoa_url url) {
Gfo_qarg_itm[] args = url.Qargs_ary();
if (args == null) return null;
if (args == null) return Xoctg_catpage_url.New__blank();
int len = args.length;
if (len == 0) return Xoctg_catpage_url.New__blank();
// init caturl structs
byte[][] keys = new byte[Xoa_ctg_mgr.Tid___max][];
boolean[] fwds = new boolean[Xoa_ctg_mgr.Tid___max];
for (int i = 0; i < Xoa_ctg_mgr.Tid___max; ++i) {
fwds[i] = Bool_.Y;
keys[i] = Bry_.Empty;
}
Bry_bfr tmp_bfr = Bry_bfr_.New();
// loop qargs; EX: "?subcatfrom=B&filefrom=C&pagefrom=D"
int len = args.length;
for (int i = 0; i < len; ++i) {
Gfo_qarg_itm arg = args[i];

@ -1,62 +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.addons.wikis.ctgs.htmls.catpages.utls; 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.core.lists.binary_searches.*;
import gplx.xowa.addons.wikis.ctgs.htmls.catpages.doms.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.urls.*;
public class Xoctg_catpage_filter {
public static void Filter(int limit, Xoctg_catpage_url cat_url, Xoctg_catpage_ctg ctg) {
int len = Xoa_ctg_mgr.Tid___max;
for (byte i = 0; i < len; ++i) {
Filter_by_grp(limit, cat_url, ctg.Grp_by_tid(i));
}
}
private static void Filter_by_grp(int grp_len, Xoctg_catpage_url cat_url, Xoctg_catpage_grp grp) {
byte grp_tid = grp.Tid();
byte[] grp_key = cat_url.Grp_keys()[grp_tid];
// dflt to bos; EX: grp_bgn=0 grp_end=200
int grp_bgn = 0;
int grp_end = grp_bgn + grp_len;
// key specified; calc new grp_bgn, grp_end
if (grp_key != null) {
// get idx of key
int key_idx = Binary_search_.Search(grp.Itms(), Xoctg_catpage_itm_sorter__sort_key.Sorter, grp_key);
// if fwd, set grp_bgn to key_idx, and add grp_len
if (cat_url.Grp_fwds()[grp_tid]) {
grp_bgn = key_idx;
grp_end = grp_bgn + grp_len;
}
// if bwd, set grp_end to key_idx, and subtract grp_len
else {
grp_end = key_idx;
grp_bgn = grp_end - grp_len;
// assert new grp_bgn is not negative
if (grp_bgn < 0) grp_bgn = 0;
}
}
// assert new grp_end is not > grp_max; note that this needs to be specified for when grp_key is null and not null
int grp_max = grp.Itms__len();
if (grp_end > grp_max)
grp_end = grp_max;
grp.Rng_(grp_bgn, grp_end);
}
}

@ -1,107 +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.addons.wikis.ctgs.htmls.catpages.utls; 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 org.junit.*; import gplx.core.tests.*;
import gplx.xowa.apps.urls.*;
import gplx.xowa.addons.wikis.ctgs.htmls.catpages.doms.*; import gplx.xowa.addons.wikis.ctgs.htmls.catpages.urls.*;
public class Xoctg_catpage_filter__tst {
private final Xoctg_catpage_filter__fxt fxt = new Xoctg_catpage_filter__fxt();
private Xoctg_catpage_ctg ctg;
@Before public void init() {
this.ctg = fxt.Make__ctg(25, 25, 25);
}
@Test public void Initial() {
fxt.Exec__filter(5, "A", ctg);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__subc, 0, 5);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__page, 0, 5);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__file, 0, 5);
}
@Test public void Fwd__page__05() {
fxt.Exec__filter(5, "A?pagefrom=05", ctg);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__page, 5, 10);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__subc, 0, 5);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__file, 0, 5);
}
@Test public void Fwd__page__10() {
fxt.Exec__filter(5, "A?pagefrom=10", ctg);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__page, 10, 15);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__subc, 0, 5);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__file, 0, 5);
}
@Test public void Fwd__page__23() {
fxt.Exec__filter(5, "A?pagefrom=23", ctg);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__page, 23, 25);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__subc, 0, 5);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__file, 0, 5);
}
@Test public void Fwd__full__06() {
fxt.Exec__filter(5, "A?from=06", ctg);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__page, 6, 11);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__subc, 6, 11);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__file, 6, 11);
}
@Test public void Bwd__page__20() {
fxt.Exec__filter(5, "A?pageuntil=20", ctg);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__page, 15, 20);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__subc, 0, 5);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__file, 0, 5);
}
@Test public void Bwd__page__2() {
fxt.Exec__filter(5, "A?pageuntil=01", ctg);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__page, 0, 1);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__subc, 0, 5);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__file, 0, 5);
}
@Test public void Bwd__full__11() {
fxt.Exec__filter(5, "A?until=11", ctg);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__page, 6, 11);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__subc, 6, 11);
fxt.Test__cat_grp(ctg, Xoa_ctg_mgr.Tid__file, 6, 11);
}
}
class Xoctg_catpage_filter__fxt {
private Xow_url_parser url_parser;
public Xoctg_catpage_filter__fxt() {
Xoa_app app = Xoa_app_fxt.Make__app__edit();
this.url_parser = app.User().Wikii().Utl__url_parser();
}
public Xoctg_catpage_ctg Make__ctg(int subc, int page, int file) {
Xoctg_catpage_ctg ctg = new Xoctg_catpage_ctg(Bry_.new_a7("A"));
Make__ctg_grp(ctg, Xoa_ctg_mgr.Tid__subc, subc);
Make__ctg_grp(ctg, Xoa_ctg_mgr.Tid__page, page);
Make__ctg_grp(ctg, Xoa_ctg_mgr.Tid__file, file);
return ctg;
}
private void Make__ctg_grp(Xoctg_catpage_ctg ctg, byte tid, int count) {
Xoctg_catpage_grp grp = ctg.Grp_by_tid(tid);
for (int i = 0; i < count; ++i) {
Xoctg_catpage_itm itm = new Xoctg_catpage_itm(i * tid, Xoa_ttl.Null, Bry_.new_a7(Int_.To_str_pad_bgn_zero(i, 2)));
grp.Itms__add(itm);
}
grp.Itms__make();
}
public void Exec__filter(int limit, String cat_url_str, Xoctg_catpage_ctg ctg) {
Xoctg_catpage_url cat_url = Xoctg_catpage_url_parser.Parse(url_parser.Parse(Bry_.new_a7(cat_url_str)));
Xoctg_catpage_filter.Filter(limit, cat_url, ctg);
}
public void Test__cat_grp(Xoctg_catpage_ctg ctg, byte tid, int expd_bgn, int expd_end) {
Xoctg_catpage_grp grp = ctg.Grp_by_tid(tid);
Gftest.Eq__int(expd_bgn, grp.Bgn(), "bgn failed; tid={0}", tid);
Gftest.Eq__int(expd_end, grp.End(), "end failed; tid={0}", tid);
}
}

@ -1,120 +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.addons.wikis.ctgs.htmls.catpages.utls; 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.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.*;
public class Xoctg_catpage_loader {
private static final Object thread_lock = new Object();
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.Log_many("", "", "category does not exist in cat_core table; ttl=~{0}", cat_ttl.Full_db()); // NOTE: this is not rare as Category pages can be created as deliberately empty, or as redirects; fr.w:Catégorie:Utilisateur_hess-4; DATE:2016-09-12
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);
// run sql and create itms based on cat_link
Db_rdr rdr = Db_rdr_.Empty;
synchronized (thread_lock) { // LOCK:used by multiple wrks; DATE:2016-09-12
try {
attach_mgr.Attach();
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)
);
}
}

@ -31,7 +31,7 @@ class Xoctg_pagebox_loader implements Select_in_cbk {
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);
Gfo_usr_dlg_.Instance.Warn_many("", "", "cat_id in cat_link but not in cat_core; page=~{0} cat_id=~{1}", 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"));
}

@ -46,7 +46,7 @@ public class Xoctg_pagebox_wtr {
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());
boolean exists = wiki.Data__core_mgr().Tbl__page().Select_by_ttl(tmp_page_itm, page.Ttl().Ns(), page.Ttl().Page_db());
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);

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

Loading…
Cancel
Save