1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2026-03-02 03:49:30 +00:00
This commit is contained in:
gnosygnu
2015-07-12 21:10:02 -04:00
commit 794b5a232f
3099 changed files with 238212 additions and 0 deletions

32
400_xowa/.classpath Normal file
View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="src_040_io"/>
<classpathentry kind="src" path="src_060_utl"/>
<classpathentry kind="src" path="src_100_app"/>
<classpathentry kind="src" path="src_120_wiki"/>
<classpathentry kind="src" path="src_121_wiki_data"/>
<classpathentry kind="src" path="src_140_lang"/>
<classpathentry kind="src" path="src_160_file"/>
<classpathentry kind="src" path="src_161_meta"/>
<classpathentry kind="src" path="src_200_bldr"/>
<classpathentry kind="src" path="src_210_bldr_core"/>
<classpathentry kind="src" path="src_240_install"/>
<classpathentry kind="src" path="src_300_html"/>
<classpathentry kind="src" path="src_310_url"/>
<classpathentry kind="src" path="src_400_parser"/>
<classpathentry kind="src" path="src_405_tkn"/>
<classpathentry kind="src" path="src_409_tkn_misc"/>
<classpathentry kind="src" path="src_440_lnki"/>
<classpathentry kind="src" path="src_490_xnde"/>
<classpathentry kind="src" path="src_500_tmpl"/>
<classpathentry kind="src" path="xtn"/>
<classpathentry combineaccessrules="false" kind="src" path="/100_core"/>
<classpathentry combineaccessrules="false" kind="src" path="/150_gfui"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry combineaccessrules="false" kind="src" path="/140_dbs"/>
<classpathentry kind="lib" path="lib/luaj_xowa.jar"/>
<classpathentry kind="lib" path="lib/jtidy_xowa.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/>
</classpath>

17
400_xowa/.project Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>400_xowa</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

BIN
400_xowa/lib/jtidy_xowa.jar Normal file

Binary file not shown.

BIN
400_xowa/lib/luaj_xowa.jar Normal file

Binary file not shown.

View File

@@ -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.cache; import gplx.*;
public class Gfo_cache_mgr_base {
private Ordered_hash hash = Ordered_hash_.new_bry_();
public int Compress_max() {return compress_max;} public void Compress_max_(int v) {compress_max = v;} private int compress_max = 16;
public int Compress_to() {return compress_to;} public void Compress_to_(int v) {compress_to = v;} private int compress_to = 8;
protected Object Base_get_or_null(byte[] key) {
Object rv_obj = hash.Get_by(key);
return rv_obj == null ? null : ((Gfo_cache_itm)rv_obj).Val();
}
protected void Base_add(byte[] key, Object val) {
if (hash.Count() >= compress_max) Compress();
Gfo_cache_itm itm = new Gfo_cache_itm(key, val);
hash.Add(key, itm);
}
protected void Base_del(byte[] key) {
hash.Del(key);
}
public void Compress() {
hash.Sort_by(Gfo_cache_itm_comparer.Touched_asc);
int del_len = hash.Count() - compress_to;
List_adp del_list = List_adp_.new_();
for (int i = 0; i < del_len; i++) {
Gfo_cache_itm itm = (Gfo_cache_itm)hash.Get_at(i);
del_list.Add(itm);
}
for (int i = 0; i < del_len; i++) {
Gfo_cache_itm itm = (Gfo_cache_itm)del_list.Get_at(i);
hash.Del(itm.Key());
}
}
}

View File

@@ -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.cache; import gplx.*;
import gplx.core.primitives.*;
public class Gfo_cache_mgr_bry extends Gfo_cache_mgr_base {
public Object Get_or_null(byte[] key) {return Base_get_or_null(key);}
public void Add(byte[] key, Object val) {Base_add(key, val);}
public void Del(byte[] key) {Base_del(key);}
}
class Gfo_cache_itm {
public Gfo_cache_itm(Object key, Object val) {this.key = key; this.val = val; this.Touched_update();}
public Object Key() {return key;} private Object key;
public Object Val() {return val;} private Object val;
public long Touched() {return touched;} private long touched;
public Gfo_cache_itm Touched_update() {touched = Env_.TickCount(); return this;}
}
class Gfo_cache_itm_comparer implements gplx.lists.ComparerAble {
public int compare(Object lhsObj, Object rhsObj) {
Gfo_cache_itm lhs = (Gfo_cache_itm)lhsObj;
Gfo_cache_itm rhs = (Gfo_cache_itm)rhsObj;
return Long_.Compare(lhs.Touched(), rhs.Touched());
}
public static final Gfo_cache_itm_comparer Touched_asc = new Gfo_cache_itm_comparer();
}
class Io_url_exists_mgr {
private gplx.cache.Gfo_cache_mgr_bry cache_mgr = new gplx.cache.Gfo_cache_mgr_bry();
public Io_url_exists_mgr() {
cache_mgr.Compress_max_(Int_.MaxValue);
}
public boolean Has(Io_url url) {
byte[] url_key = url.RawBry();
Object rv_obj = cache_mgr.Get_or_null(url_key);
if (rv_obj != null) return ((Bool_obj_ref)rv_obj).Val(); // cached val exists; use it
boolean exists = Io_mgr.I.ExistsFil(url);
cache_mgr.Add(url_key, Bool_obj_ref.new_(exists));
return exists;
}
}

View File

@@ -0,0 +1,123 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.core.brys; import gplx.*; import gplx.core.*;
public class Bit_ {
public static String XtoBitStr(int val) {
boolean[] bits = new boolean[8];
int idx = 7;
while (val > 0) {
if ((val & 1) == 1) bits[idx] = true;
idx--;
val >>= 1;
}
byte[] rv = new byte[8];
for (int i = 0; i < 8; i++)
rv[i] = bits[i] ? Byte_ascii.Num_1 : Byte_ascii.Num_0;
return String_.new_a7(rv);
}
public static int[] Bld_pow_ary(int... seg_ary) {
int seg_ary_len = seg_ary.length;
int pow = 0;
int[] rv = new int[seg_ary_len];
for (int i = seg_ary_len - 1; i > -1; i--) {
rv[i] = Base2_ary[pow];
pow += seg_ary[i];
}
return rv;
}
public static int Xto_int(int[] pow_ary, int[] val_ary) {
int pow_ary_last = pow_ary.length - 1;
int val = 0;
for (int i = pow_ary_last; i > -1; i--)
val += pow_ary[i] * val_ary[i];
return val;
}
public static int[] Xto_intAry(int[] pow_ary, int v) {
int[] rv = new int[pow_ary.length];
Xto_intAry(rv, pow_ary, v);
return rv;
}
public static void Xto_intAry(int[] rv, int[] pow_ary, int v) {
int pow_ary_len = pow_ary.length;
int rv_len = rv.length;
for (int i = 0; i < pow_ary_len; i++) {
if (i >= rv_len) break;
rv[i] = v / pow_ary[i];
int factor = pow_ary[i] * rv[i];
v = factor == 0 ? v : (v % factor); // NOTE: if 0, do not do modulus or else div by zero
}
}
public static byte Xto_byte(byte[] pow_ary, byte... val_ary) {
int pow_ary_last = pow_ary.length - 1;
int val = 0;
for (int i = pow_ary_last; i > -1; --i)
val += pow_ary[i] * val_ary[i];
return (byte)val;
}
public static void Xto_bry(byte[] rv, byte[] pow_ary, byte val) {
int pow_ary_len = pow_ary.length;
int rv_len = rv.length;
for (int i = 0; i < pow_ary_len; i++) {
if (i >= rv_len) break;
rv[i] = (byte)(val / pow_ary[i]);
int factor = pow_ary[i] * rv[i];
val = (byte)(factor == 0 ? val : (val % factor)); // NOTE: if 0, do not do modulus or else div by zero
}
}
public static int Shift_lhs(int val, int shift) {return val << shift;}
public static int Shift_rhs(int val, int shift) {return val >> shift;}
public static int Shift_lhs_to_int(int[] shift_ary, int... val_ary) {
int val_len = val_ary.length; if (val_len > shift_ary.length) throw Exc_.new_("vals must be less than shifts", "vals", val_len, "shifts", shift_ary.length);
int rv = 0;
for (int i = 0; i < val_len; ++i) {
int val = val_ary[i];
int shift = shift_ary[i];
rv += val << shift;
}
return rv;
}
public static void Shift_rhs_to_ary(int[] rv, int[] shift_ary, int val) {
int shift_len = shift_ary.length;
for (int i = shift_len - 1; i > - 1; --i) {
int shift = shift_ary[i];
int itm = val >> shift;
rv[i] = itm;
val -= (itm << shift);
}
}
public static int Xto_int_date_short(int[] val_ary) {
val_ary[0] -= 1900;
return Xto_int(Pow_ary_date_short, val_ary);
}
public static void Xto_date_short_int_ary(int[] rv, int v) {
Xto_intAry(rv, Pow_ary_date_short, v);
rv[0] += 1900;
}
public static DateAdp Xto_date_short(int v) {
int[] rv = new int[Pow_ary_date_short.length];
Xto_date_short_int_ary(rv, v);
return DateAdp_.seg_(rv);
}
private static final int[] Pow_ary_date_short = new int[] {1048576, 65536, 2048, 64, 1}; // yndhm -> 12,4,5,5,6
private static final int[] Base2_ary = new int[]
{ 1, 2, 4, 8, 16, 32, 64, 128
, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768
, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608
, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 0
};
}

View File

@@ -0,0 +1,109 @@
/*
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.brys; import gplx.*; import gplx.core.*;
import org.junit.*;
public class Bit__tst {
@Before public void init() {fxt.Clear();} private Bit__fxt fxt = new Bit__fxt();
@Test public void XtoBitStr() {
tst_XtoBitStr( 0, "00000000");
tst_XtoBitStr( 1, "00000001");
tst_XtoBitStr( 2, "00000010");
tst_XtoBitStr( 3, "00000011");
tst_XtoBitStr(255, "11111111");
} void tst_XtoBitStr(int val, String expd) {Tfds.Eq(expd, Bit_.XtoBitStr(val));}
@Test public void Bld_pow_ary() {
tst_Bld_pow_ary(ary_(1, 1, 1, 1), ary_(8, 4, 2, 1));
tst_Bld_pow_ary(ary_(3, 2) , ary_(4, 1));
} void tst_Bld_pow_ary(int[] seg_ary, int[] expd) {Tfds.Eq_ary_str(expd, Bit_.Bld_pow_ary(seg_ary));}
@Test public void Xto_int() {
tst_Xto_int(ary_(1, 1, 1, 1) , ary_(1, 1, 1, 1), 15);
tst_Xto_int(ary_(1, 1, 1, 1) , ary_(0, 0, 0, 0), 0);
tst_Xto_int(ary_(1, 1, 1, 1) , ary_(1, 0, 0, 1), 9);
tst_Xto_int(ary_(1, 1, 1, 1) , ary_(0, 1, 1, 0), 6);
tst_Xto_int(ary_(3, 2) , ary_(7, 3) , 31);
tst_Xto_int(ary_(3, 2, 1) , ary_(7, 3, 1) , 63);
tst_Xto_int(ary_(11, 4, 5, 5, 6), ary_(2012, 6, 3, 23, 17), 2110135761);
tst_Xto_int(ary_(11, 4, 5, 5, 6), ary_(2012, 6, 3, 23, 18), 2110135762);
}
private void tst_Xto_int(int[] seg_ary, int[] val_ary, int expd) {
int[] pow_ary = Bit_.Bld_pow_ary(seg_ary);
Tfds.Eq(expd, Bit_.Xto_int(pow_ary, val_ary));
}
@Test public void Xto_intAry() {
tst_Xto_intAry(ary_(1, 1, 1, 1) , 15, ary_(1, 1, 1, 1));
tst_Xto_intAry(ary_(3, 2) , 31, ary_(7, 3));
tst_Xto_intAry(ary_(3, 2, 1) , 63, ary_(7, 3, 1));
tst_Xto_intAry(ary_(12, 4, 5, 5, 6), 2110135761, ary_(2012, 6, 3, 23, 17));
tst_Xto_intAry(ary_(12, 4, 5, 5, 6), 2110135762, ary_(2012, 6, 3, 23, 18));
}
private void tst_Xto_intAry(int[] seg_ary, int val, int[] expd) {
int[] pow_ary = Bit_.Bld_pow_ary(seg_ary);
Tfds.Eq_ary_str(expd, Bit_.Xto_intAry(pow_ary, val));
}
int[] ary_(int... v) {return v;}
@Test public void Xto_int_date_short() {
tst_Xto_int_date_short("20120604 2359", 117843451);
tst_Xto_int_date_short("20120604 2358", 117843450);
tst_Xto_int_date_short("20120605 0000", 117843968);
}
private void tst_Xto_int_date_short(String date_str, int expd) {
DateAdp date = DateAdp_.parse_fmt(date_str, "yyyyMMdd HHmm");
int date_int = Bit_.Xto_int_date_short(date.XtoSegAry());
Tfds.Eq(expd, date_int);
Tfds.Eq(date_str, Bit_.Xto_date_short(date_int).XtoStr_fmt("yyyyMMdd HHmm"));
}
@Test public void Shift_lhs() {// simple: shift 1 bit
fxt.Test_shift_lhs(1, 1, 2);
fxt.Test_shift_lhs(2, 1, 4);
fxt.Test_shift_lhs(3, 1, 6);
fxt.Test_shift_lhs(4, 1, 8);
}
@Test public void Shift_rhs() {
fxt.Test_shift_rhs(2, 1, 1);
fxt.Test_shift_rhs(4, 1, 2);
fxt.Test_shift_rhs(6, 1, 3);
fxt.Test_shift_rhs(8, 1, 4);
}
@Test public void Shift_lhs_to_int() {
int[] shift_ary = Int_.Ary(0, 3, 5);
fxt.Test_shift_lhs_to_int(shift_ary, Int_.Ary(0, 0, 0), 0);
fxt.Test_shift_lhs_to_int(shift_ary, Int_.Ary(7, 0, 0), 7); // 1st 3 bits
fxt.Test_shift_lhs_to_int(shift_ary, Int_.Ary(0, 3, 0), 24); // 2nd 2 bits
fxt.Test_shift_lhs_to_int(shift_ary, Int_.Ary(0, 0, 1), 32); // 3rd 1 bit
fxt.Test_shift_lhs_to_int(shift_ary, Int_.Ary(7, 3, 1), 63); // many bits
}
@Test public void Shift_rhs_to_ary() {
int[] shift_ary = Int_.Ary(0, 3, 5);
fxt.Test_shift_rhs_to_ary(shift_ary, 0, Int_.Ary(0, 0, 0));
fxt.Test_shift_rhs_to_ary(shift_ary, 7, Int_.Ary(7, 0, 0)); // 1st 3 bits
fxt.Test_shift_rhs_to_ary(shift_ary, 24, Int_.Ary(0, 3, 0)); // 2nd 2 bits
fxt.Test_shift_rhs_to_ary(shift_ary, 32, Int_.Ary(0, 0, 1)); // 3rd 1 bit
fxt.Test_shift_rhs_to_ary(shift_ary, 63, Int_.Ary(7, 3, 1)); // many bits
}
}
class Bit__fxt {
public void Clear() {}
public void Test_shift_lhs(int val, int shift, int expd) {Tfds.Eq(expd, Bit_.Shift_lhs(val, shift));}
public void Test_shift_rhs(int val, int shift, int expd) {Tfds.Eq(expd, Bit_.Shift_rhs(val, shift));}
public void Test_shift_lhs_to_int(int[] shift_ary, int[] val_ary, int expd) {Tfds.Eq(expd, Bit_.Shift_lhs_to_int(shift_ary, val_ary));}
public void Test_shift_rhs_to_ary(int[] shift_ary, int val, int[] expd_ary) {
int[] actl_ary = Int_.Ary(0, 0, 0);
Bit_.Shift_rhs_to_ary(actl_ary, shift_ary, val);
Tfds.Eq_ary(expd_ary, actl_ary);
}
}

View File

@@ -0,0 +1,40 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.core.brys; import gplx.*; import gplx.core.*;
public class Bry_bldr {
public byte[] Val() {return val;} private byte[] val;
public Bry_bldr New_256() {return New(256);}
public Bry_bldr New(int len) {val = new byte[len]; return this;}
public Bry_bldr Set_rng_ws(byte v) {return Set_many(v, Byte_ascii.Space, Byte_ascii.Tab, Byte_ascii.Nl, Byte_ascii.Cr);}
public Bry_bldr Set_rng_xml_identifier(byte v) {return Set_rng_alpha_lc(v).Set_rng_alpha_uc(v).Set_rng_num(v).Set_many(v, Byte_ascii.Underline, Byte_ascii.Dash);}
public Bry_bldr Set_rng_alpha(byte v) {return Set_rng_alpha_lc(v).Set_rng_alpha_uc(v);}
public Bry_bldr Set_rng_alpha_lc(byte v) {return Set_rng(v, Byte_ascii.Ltr_a, Byte_ascii.Ltr_z);}
public Bry_bldr Set_rng_alpha_uc(byte v) {return Set_rng(v, Byte_ascii.Ltr_A, Byte_ascii.Ltr_Z);}
public Bry_bldr Set_rng_num(byte v) {return Set_rng(v, Byte_ascii.Num_0, Byte_ascii.Num_9);}
public Bry_bldr Set_rng(byte v, int bgn, int end) {
for (int i = bgn; i <= end; i++)
val[i] = v;
return this;
}
public Bry_bldr Set_many(byte v, int... ary) {
int len = ary.length;
for (int i = 0; i < len; i++)
val[ary[i]] = v;
return this;
}
}

View File

@@ -0,0 +1,26 @@
/*
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.brys; import gplx.*; import gplx.core.*;
import gplx.lists.*;
public class Bry_comparer implements ComparerAble {
public int compare(Object lhsObj, Object rhsObj) {
byte[] lhs = (byte[])lhsObj, rhs = (byte[])rhsObj;
return Bry_.Compare(lhs, 0, lhs.length, rhs, 0, rhs.length);
}
public static final Bry_comparer _ = new Bry_comparer(); Bry_comparer() {}
}

View File

@@ -0,0 +1,56 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.core.brys; import gplx.*; import gplx.core.*;
import org.junit.*;
public class Bry_rdr_tst {
@Before public void init() {fxt.Clear();} private Bry_rdr_fxt fxt = new Bry_rdr_fxt();
@Test public void Int() {
fxt.Init_src("12|3456|789");
fxt.Test_read_int(12);
fxt.Test_read_int(3456);
fxt.Test_read_int(789);
fxt.Test_read_int(Int_.MinValue);
}
@Test public void Int_negative() {
fxt.Init_src("-1|-2");
fxt.Test_read_int(-1);
fxt.Test_read_int(-2);
}
@Test public void Bry() {
fxt.Init_src("abc|d||ef");
fxt.Test_read_bry("abc");
fxt.Test_read_bry("d");
fxt.Test_read_bry("");
fxt.Test_read_bry("ef");
fxt.Test_read_bry(null);
}
}
class Bry_rdr_fxt {
private Bry_rdr rdr;
public void Clear() {rdr = new Bry_rdr();}
public Bry_rdr_fxt Init_src(String v) {rdr.Init(Bry_.new_u8(v)); return this;}
public Bry_rdr_fxt Init_pos(int v) {rdr.Pos_(v); return this;}
public void Test_read_int(int expd_val) {
Tfds.Eq(expd_val, rdr.Read_int_to_pipe());
}
public void Test_read_bry(String expd_str) {
byte[] actl_bry = rdr.Read_bry_to_pipe();
String actl_str = actl_bry == null ? null : String_.new_u8(actl_bry);
Tfds.Eq(expd_str, actl_str);
}
}

View File

@@ -0,0 +1,96 @@
/*
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.btries; import gplx.*; import gplx.core.*;
import org.junit.*;
import gplx.xowa.langs.cases.*;
public class Btrie_utf8_mgr_tst {
@Before public void init() {fxt.Clear();} private Btrie_utf8_mgr_fxt fxt = new Btrie_utf8_mgr_fxt();
@Test public void Ascii() {
fxt.Init_add(Bry_.new_a7("a") , "1");
fxt.Init_add(Bry_.new_a7("abc") , "123");
fxt.Test_match("a" , "1"); // single.exact
fxt.Test_match("abc" , "123"); // many.exact
fxt.Test_match("ab" , "1"); // single.more
fxt.Test_match("abcde" , "123"); // many.more
fxt.Test_match(" a" , null); // no_match
fxt.Test_match("aBC" , "123"); // upper
}
@Test public void Uft8() {
fxt.Init_add(Bry_.new_u8("aéi") , "1");
fxt.Test_match("aéi" , "1"); // exact
fxt.Test_match("aÉi" , "1"); // upper.utf8
fxt.Test_match("AÉI" , "1"); // upper.all
fxt.Test_match("AÉIo" , "1"); // trailing-char
fxt.Test_match("aei" , null); // no_match
}
@Test public void Uft8_match_pos() {
fxt.Init_add(Bry_.new_u8("aéi") , "1");
fxt.Test_match_pos("aAÉI" , 1, "1"); // match at 1
fxt.Test_match_pos("aAÉI" , 0, null); // no_match at 0
}
@Test public void Uft8_asymmetric() {
fxt.Init_add(Bry_.new_u8("İ") , "1");
fxt.Test_match("İ" , "1"); // exact=y; İ = Bry_.ints_(196,176)
fxt.Test_match("i" , "1"); // lower=y; i = Bry_.ints_(105)
fxt.Test_match("I" , null); // upper=n; I = Bry_.ints_( 73); see Btrie_utf8_itm and rv.asymmetric_bry
fxt.Clear();
fxt.Init_add(Bry_.new_u8("i") , "1");
fxt.Test_match("i" , "1"); // exact=y
fxt.Test_match("I" , "1"); // upper=y
fxt.Test_match("İ" , null); // utf_8=n; note that a trie with "i" doesn't match a src with "İ" even though "İ" lower-cases to "i"
}
@Test public void Utf8_asymmetric_multiple() { // PURPOSE: problems in original implementation of Hash_adp_bry and uneven source / target counts;
fxt.Init_add(Bry_.new_u8("İİ") , "1");
fxt.Test_match("İİ" , "1"); // exact
fxt.Test_match("ii" , "1"); // lower
fxt.Test_match("İi" , "1"); // mixed
fxt.Test_match("" , "1"); // mixed
}
@Test public void Utf8_asymmetric_upper() { // PURPOSE: "İ" and "I" should co-exist; see Btrie_utf8_itm and called_by_match
fxt.Init_add(Bry_.new_u8("İ") , "1");
fxt.Init_add(Bry_.new_u8("I") , "1");
fxt.Test_match("İ" , "1"); // exact
fxt.Test_match("I" , "1"); // exact
fxt.Test_match("i" , "1"); // lower
}
@Test public void Utf8_asymmetric_symbols() { // PURPOSE: test Hash_adp_bry and multi-byte syms (chars that will never be cased)
fxt.Init_add(Bry_.new_u8("a_b") , "1");
fxt.Test_match("a_b" , "1"); // exact: len=3
fxt.Test_match("a†b" , null); // diff : len=3
fxt.Test_match("a±b" , null); // diff : len=2
fxt.Test_match("a_b" , null); // diff : len=1
}
}
class Btrie_utf8_mgr_fxt {
private Btrie_utf8_mgr trie;
public void Clear() {
trie = Btrie_utf8_mgr.new_(Xol_case_mgr_.Utf8());
}
public void Init_add(byte[] key, Object val) {trie.Add_obj(key, val);}
public void Test_match_pos(String src_str, int bgn_pos, String expd) {
byte[] src = Bry_.new_u8(src_str);
Object actl = trie.Match_bgn_w_byte(src[bgn_pos], src, bgn_pos, src.length);
Tfds.Eq(expd, actl, src_str);
}
public void Test_match(String src_str, String expd) {
byte[] src = Bry_.new_u8(src_str);
Object actl = trie.Match_bgn_w_byte(src[0], src, 0, src.length);
Tfds.Eq(expd, actl, src_str);
}
}

View File

@@ -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.enums; import gplx.*; import gplx.core.*;
class Gfo_enum_grp {
// private Ordered_hash itms = Ordered_hash_.new_();
public Gfo_enum_grp(Guid_adp uid, String key, int id, String name, int sort, String xtn) {
this.uid = uid; this.key = key; this.id = id; this.name = name; this.sort = sort; this.xtn = xtn;
}
public Guid_adp Uid() {return uid;} private Guid_adp uid;
public String Key() {return key;} private String key;
public int Id() {return id;} private int id;
public String Name() {return name;} private String name;
public int Sort() {return sort;} private int sort;
public String Xtn() {return xtn;} private String xtn;
}
class Gfo_enum_itm {
public Gfo_enum_itm(Guid_adp uid, String key, int id, String name, int sort, String xtn) {
this.uid = uid; this.key = key; this.id = id; this.name = name; this.sort = sort; this.xtn = xtn;
}
public Guid_adp Uid() {return uid;} private Guid_adp uid;
public String Key() {return key;} private String key;
public int Id() {return id;} private int id;
public String Name() {return name;} private String name;
public int Sort() {return sort;} private int sort;
public String Xtn() {return xtn;} private String xtn;
}
/*
enum_grps
grp_guid,grp_key,grp_int,grp_name,grp_sort,grp_xtn
0-1-2-3,xowa.wiki,0,wiki,,
enum_itms
grp_int,itm_guid,itm_key,itm_int,itm_name,itm_sort,itm_xtn
1,0-1-2-3,0,en.wikipedia.org,0,enwiki,0,''
class Gfo_enum_mgr {
// public Gui
}
*/

View File

@@ -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.flds; import gplx.*; import gplx.core.*;
public class Gfo_fld_base {
public byte Row_dlm() {return row_dlm;} public Gfo_fld_base Row_dlm_(byte v) {row_dlm = v; return this;} protected byte row_dlm = Byte_ascii.Nl;
public byte Fld_dlm() {return fld_dlm;} public Gfo_fld_base Fld_dlm_(byte v) {fld_dlm = v; return this;} protected byte fld_dlm = Byte_ascii.Pipe;
public byte Escape_dlm() {return escape_dlm;} public Gfo_fld_base Escape_dlm_(byte v) {escape_dlm = v; return this;} protected byte escape_dlm = Byte_ascii.Tilde;
public byte Quote_dlm() {return quote_dlm;} public Gfo_fld_base Quote_dlm_(byte v) {quote_dlm = v; return this;} protected byte quote_dlm = Byte_ascii.Nil;
public Gfo_fld_base Escape_reg(byte b) {return Escape_reg(b, b);}
public byte[] Escape_decode() {return decode_regy;}
public Gfo_fld_base Escape_reg(byte key, byte val) {encode_regy[key] = val; decode_regy[val] = key; return this;} protected byte[] decode_regy = new byte[256]; protected byte[] encode_regy = new byte[256];
public Gfo_fld_base Escape_clear() {
for (int i = 0; i < 256; i++)
decode_regy[i] = Byte_ascii.Nil;
for (int i = 0; i < 256; i++)
encode_regy[i] = Byte_ascii.Nil;
return this;
}
Gfo_fld_base Ini_common() {
return Escape_reg(Byte_ascii.Nl, Byte_ascii.Ltr_n).Escape_reg(Byte_ascii.Tab, Byte_ascii.Ltr_t).Escape_reg(Byte_ascii.Cr, Byte_ascii.Ltr_r)
.Escape_reg(Byte_ascii.Backfeed, Byte_ascii.Ltr_b); // .Escape_reg(Byte_ascii.Nil, Byte_ascii.Num_0)
}
protected Gfo_fld_base Ctor_xdat_base() {
return Escape_clear().Ini_common()
.Fld_dlm_(Byte_ascii.Pipe).Row_dlm_(Byte_ascii.Nl).Escape_dlm_(Byte_ascii.Tilde).Quote_dlm_(Byte_ascii.Nil)
.Escape_reg(Byte_ascii.Pipe, Byte_ascii.Ltr_p).Escape_reg(Byte_ascii.Tilde);
}
protected Gfo_fld_base Ctor_sql_base() {
return Escape_clear().Ini_common()
.Fld_dlm_(Byte_ascii.Comma).Row_dlm_(Byte_ascii.Paren_end).Escape_dlm_(Byte_ascii.Backslash).Quote_dlm_(Byte_ascii.Apos)
.Escape_reg(Byte_ascii.Backslash).Escape_reg(Byte_ascii.Quote).Escape_reg(Byte_ascii.Apos); // , Escape_eof = Bry_.new_u8("\\Z")
}
}

View File

@@ -0,0 +1,124 @@
/*
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.flds; import gplx.*; import gplx.core.*;
public class Gfo_fld_rdr extends Gfo_fld_base {
private Bry_bfr bfr = Bry_bfr.new_(); private static final byte[] Bry_nil = Bry_.new_a7("\\0");
public byte[] Data() {return data;} public Gfo_fld_rdr Data_(byte[] v) {data = v; data_len = v.length; pos = 0; return this;} private byte[] data; int data_len;
public int Pos() {return pos;} public Gfo_fld_rdr Pos_(int v) {pos = v; return this;} private int pos;
public int Fld_bgn() {return fld_bgn;} public Gfo_fld_rdr Fld_bgn_(int v) {fld_bgn = v; return this;} private int fld_bgn;
public int Fld_end() {return fld_end;} public Gfo_fld_rdr Fld_end_(int v) {fld_end = v; return this;} private int fld_end;
public int Fld_idx() {return fld_idx;} private int fld_idx;
public int Row_idx() {return row_idx;} private int row_idx;
public void Ini(byte[] data, int pos) {this.data = data; this.data_len = data.length; this.pos = pos;}
public String Read_str_simple() {Move_next_simple(); return String_.new_u8(data, fld_bgn, fld_end);}
public byte[] Read_bry_simple() {Move_next_simple(); return Bry_.Mid(data, fld_bgn, fld_end);} // was Mid_by_len???; 20120915
public int Read_int_base85_lenN(int len) {fld_bgn = pos; fld_end = pos + len - 1 ; pos = pos + len + 1 ; return Base85_utl.XtoIntByAry(data, fld_bgn, fld_end);}
public int Read_int_base85_len5() {fld_bgn = pos; fld_end = pos + 4 ; pos = pos + 6 ; return Base85_utl.XtoIntByAry(data, fld_bgn, fld_end);}
public int Read_int() {Move_next_simple(); return Bry_.Xto_int_or(data, fld_bgn, fld_end, -1);}
public byte Read_int_as_byte() {Move_next_simple(); return (byte)Bry_.Xto_int_or(data, fld_bgn, fld_end, -1);}
public byte Read_byte() {Move_next_simple(); return data[fld_bgn];}
public double Read_double() {Move_next_simple(); return Bry_.XtoDoubleByPos(data, fld_bgn, fld_end);}
public DateAdp Read_dte() {// NOTE: fmt = yyyyMMdd HHmmss.fff
int y = 0, M = 0, d = 0, H = 0, m = 0, s = 0, f = 0;
if (pos < data_len && data[pos] == row_dlm) {++pos; ++row_idx; fld_idx = 0;} fld_bgn = pos;
y += (data[fld_bgn + 0] - Byte_ascii.Num_0) * 1000;
y += (data[fld_bgn + 1] - Byte_ascii.Num_0) * 100;
y += (data[fld_bgn + 2] - Byte_ascii.Num_0) * 10;
y += (data[fld_bgn + 3] - Byte_ascii.Num_0);
M += (data[fld_bgn + 4] - Byte_ascii.Num_0) * 10;
M += (data[fld_bgn + 5] - Byte_ascii.Num_0);
d += (data[fld_bgn + 6] - Byte_ascii.Num_0) * 10;
d += (data[fld_bgn + 7] - Byte_ascii.Num_0);
H += (data[fld_bgn + 9] - Byte_ascii.Num_0) * 10;
H += (data[fld_bgn + 10] - Byte_ascii.Num_0);
m += (data[fld_bgn + 11] - Byte_ascii.Num_0) * 10;
m += (data[fld_bgn + 12] - Byte_ascii.Num_0);
s += (data[fld_bgn + 13] - Byte_ascii.Num_0) * 10;
s += (data[fld_bgn + 14] - Byte_ascii.Num_0);
f += (data[fld_bgn + 16] - Byte_ascii.Num_0) * 100;
f += (data[fld_bgn + 17] - Byte_ascii.Num_0) * 10;
f += (data[fld_bgn + 18] - Byte_ascii.Num_0);
if (data[fld_bgn + 19] != fld_dlm) throw Exc_.new_("csv date is invalid", "txt", String_.new_u8_by_len(data, fld_bgn, 20));
fld_end = pos + 20;
pos = fld_end + 1; ++fld_idx;
return DateAdp_.new_(y, M, d, H, m, s, f);
}
public void Move_next_simple() {
if (pos < data_len) {
byte b_cur = data[pos];
if (b_cur == row_dlm) {
fld_bgn = fld_end = pos;
++pos; ++row_idx;
fld_idx = 0;
return;
}
}
fld_bgn = pos;
if (fld_bgn == data_len) {fld_end = data_len; return;}
for (int i = fld_bgn; i < data_len; i++) {
byte b = data[i];
if (b == fld_dlm || b == row_dlm) {
fld_end = i; pos = i + 1; ++fld_idx; // position after dlm
return;
}
}
throw Exc_.new_("fld_dlm failed", "fld_dlm", (char)fld_dlm, "bgn", fld_bgn);
}
public String Read_str_escape() {Move_next_escaped(bfr); return String_.new_u8(bfr.Xto_bry_and_clear());}
public byte[] Read_bry_escape() {Move_next_escaped(bfr); return bfr.Xto_bry_and_clear();}
public void Move_1() {++pos;}
public void Move_next_escaped() {Move_next_escaped(bfr); bfr.Clear();}
public int Move_next_simple_fld() {
Move_next_simple();
return fld_end;
}
public int Move_next_escaped(Bry_bfr trg) {
//if (pos < data_len && data[pos] == row_dlm) {++pos; ++row_idx; fld_idx = 0;} // REMOVE:20120919: this will fail for empty fields at end of line; EX: "a|\n"; intent was probably to auto-advance to new row, but this intent should be explicit
fld_bgn = pos;
boolean quote_on = false;
for (int i = fld_bgn; i < data_len; i++) {
byte b = data[i];
if ((b == fld_dlm || b == row_dlm) && !quote_on) {
fld_end = i; pos = i + 1; ++fld_idx; // position after dlm
return pos;
}
else if (b == escape_dlm) {
++i;
// if (i == data_len) throw Err_.new_("escape char at end of String");
b = data[i];
byte escape_val = decode_regy[b];
if (escape_val == Byte_ascii.Nil) {trg.Add_byte(escape_dlm).Add_byte(b);} //throw Err_.new_fmt_("unknown escape key: key={0}", data[i]);
else trg.Add_byte(escape_val);
}
else if (b == Byte_ascii.Nil) {
trg.Add(Bry_nil);
}
else if (b == quote_dlm) {
quote_on = !quote_on;
}
else
trg.Add_byte(b);
}
return -1;
}
public Gfo_fld_rdr Ctor_xdat() {return (Gfo_fld_rdr)super.Ctor_xdat_base();}
public Gfo_fld_rdr Ctor_sql() {return (Gfo_fld_rdr)super.Ctor_sql_base();}
public static Gfo_fld_rdr xowa_() {return new Gfo_fld_rdr().Ctor_xdat();}
public static Gfo_fld_rdr sql_() {return new Gfo_fld_rdr().Ctor_sql();}
}

View File

@@ -0,0 +1,56 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.core.flds; import gplx.*; import gplx.core.*;
import org.junit.*;
import gplx.ios.*;
public class Gfo_fld_rdr_tst {
Gfo_fld_rdr_fxt fxt = new Gfo_fld_rdr_fxt();
@Test public void Read_int() {fxt.ini_xdat().Raw_("123|") .tst_Read_int(123);}
@Test public void Read_double() {fxt.ini_xdat().Raw_("1.23|") .tst_Read_double(1.23);}
@Test public void Read_str_simple() {fxt.ini_xdat().Raw_("ab|") .tst_Read_str_simple("ab");}
@Test public void Read_str_escape_pipe() {fxt.ini_xdat().Raw_("a~pb|") .tst_Read_str_escape("a|b");}
@Test public void Read_str_escape_tilde() {fxt.ini_xdat().Raw_("a~~b|") .tst_Read_str_escape("a~b");}
@Test public void Read_str_escape_nl() {fxt.ini_xdat().Raw_("a~nb|") .tst_Read_str_escape("a\nb");}
@Test public void Read_str_escape_tab() {fxt.ini_xdat().Raw_("a~tb|") .tst_Read_str_escape("a\tb");}
@Test public void Write_str_escape_pipe() {fxt.ini_xdat().tst_Write_str_escape("a|b", "a~pb|");}
@Test public void Read_str_quoted_comma() {fxt.ini_sql ().Raw_("'a,b',") .tst_Read_str_escape("a,b");}
@Test public void Read_str_quoted_apos() {fxt.ini_sql ().Raw_("'a\\'b',") .tst_Read_str_escape("a'b");}
@Test public void Read_multiple() {
fxt.ini_xdat().Raw_("ab|1|.9|\n")
.tst_Read_str_escape("ab").tst_Read_int(1).tst_Read_double(.9)
;
}
@Test public void Read_dlm_nl() {fxt.ini_xdat().Raw_("123\n") .tst_Read_int(123);}
}
class Gfo_fld_rdr_fxt {
Gfo_fld_rdr rdr = new Gfo_fld_rdr(); Gfo_fld_wtr wtr = Gfo_fld_wtr.xowa_();
public Gfo_fld_rdr_fxt Raw_(String v) {rdr.Data_(Bry_.new_u8(v)); return this;}
public Gfo_fld_rdr_fxt ini_xdat() {rdr.Ctor_xdat(); return this;}
public Gfo_fld_rdr_fxt ini_sql() {rdr.Ctor_sql(); return this;}
public Gfo_fld_rdr_fxt tst_Read_int(int expd) {Tfds.Eq(expd, rdr.Read_int()); return this;}
public Gfo_fld_rdr_fxt tst_Read_double(double expd) {Tfds.Eq(expd, rdr.Read_double()); return this;}
public Gfo_fld_rdr_fxt tst_Read_str_simple(String expd) {Tfds.Eq(expd, rdr.Read_str_simple()); return this;}
public Gfo_fld_rdr_fxt tst_Read_str_escape(String expd) {Tfds.Eq(expd, rdr.Read_str_escape()); return this;}
public Gfo_fld_rdr_fxt tst_Write_str_escape(String val, String expd) {
byte[] bry = Bry_.new_u8(val);
wtr.Bfr_(bfr);
wtr.Write_bry_escape_fld(bry);
Tfds.Eq(expd, bfr.Xto_str());
return this;
} private Bry_bfr bfr = Bry_bfr.new_();
}

View File

@@ -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.core.flds; import gplx.*; import gplx.core.*;
import gplx.ios.*;
public class Gfo_fld_wtr extends Gfo_fld_base {
public Bry_bfr Bfr() {return bfr;} public Gfo_fld_wtr Bfr_(Bry_bfr v) {bfr = v; return this;} Bry_bfr bfr;
public Gfo_fld_wtr() {this.bfr = Bry_bfr.new_();}
public Gfo_fld_wtr Write_int_base85_len5_fld(int v) {bfr.Add_base85(v, Base85_utl.Len_int); bfr.Add_byte(fld_dlm); return this;}
public Gfo_fld_wtr Write_int_base85_lenN_fld(int v, int len) {bfr.Add_base85(v, len); bfr.Add_byte(fld_dlm); return this;}
public Gfo_fld_wtr Write_int_variable_fld(int v) {bfr.Add_int_variable(v); bfr.Add_byte(fld_dlm); return this;}
public Gfo_fld_wtr Write_int_fixed_fld(int v, int len) {bfr.Add_int_fixed(v, len); bfr.Add_byte(fld_dlm); return this;}
public Gfo_fld_wtr Write_double_fld(double v) {bfr.Add_double(v); bfr.Add_byte(fld_dlm); return this;}
public Gfo_fld_wtr Write_byte_fld(byte v) {bfr.Add_byte(v); bfr.Add_byte(fld_dlm); return this;}
public Gfo_fld_wtr Write_bry_escape_fld(byte[] val) {Write_bry_escape(val, 0, val.length); bfr.Add_byte(fld_dlm); return this;}
public Gfo_fld_wtr Write_bry_escape_fld(byte[] val, int bgn, int end) {Write_bry_escape(val, bgn, end); bfr.Add_byte(fld_dlm); return this;}
public Gfo_fld_wtr Write_dlm_row() { bfr.Add_byte(row_dlm); return this;}
public Gfo_fld_wtr Write_dlm_fld() { bfr.Add_byte(fld_dlm); return this;}
public Gfo_fld_wtr Write_int_base85_lenN_row(int v, int len) {bfr.Add_base85(v, len); bfr.Add_byte(row_dlm); return this;}
public Gfo_fld_wtr Write_int_base85_len5_row(int v) {bfr.Add_base85(v, Base85_utl.Len_int); bfr.Add_byte(row_dlm); return this;}
public Gfo_fld_wtr Write_bry_escape_row(byte[] val) {Write_bry_escape(val, 0, val.length); bfr.Add_byte(row_dlm); return this;}
public Gfo_fld_wtr Write_bry_escape_row(byte[] val, int bgn, int end) {Write_bry_escape(val, bgn, end); bfr.Add_byte(row_dlm); return this;}
public Gfo_fld_wtr Write_double_row(double v) {bfr.Add_double(v); bfr.Add_byte(row_dlm); return this;}
Gfo_fld_wtr Write_bry_escape(byte[] val, int bgn, int end) {
for (int i = bgn; i < end; i++) {
byte b = val[i];
byte escape_val = encode_regy[b & 0xFF]; // PATCH.JAVA:need to convert to unsigned byte
if (escape_val == Byte_ascii.Nil) bfr.Add_byte(b);
else {bfr.Add_byte(escape_dlm); bfr.Add_byte(escape_val);}
}
return this;
}
public Gfo_fld_wtr Rls() {bfr.Rls(); return this;}
public Io_url_gen Fil_gen() {return fil_gen;} public Gfo_fld_wtr Fil_gen_(Io_url_gen v) {fil_gen = v; return this;} Io_url_gen fil_gen;
public int Bfr_max() {return bfr_max;} public Gfo_fld_wtr Bfr_max_(int v) {bfr_max = v; return this;} private int bfr_max = Io_mgr.Len_mb;
public boolean Flush_needed(int v) {return bfr.Len() + v > bfr_max;}
public void Flush() {
if (Fil_gen().Cur_url() == null) fil_gen.Nxt_url();
Io_mgr.I.AppendFilBfr(fil_gen.Cur_url(), bfr);
}
public void Flush_nxt() {Flush(); fil_gen.Nxt_url();}
public Gfo_fld_wtr Ctor_xdat() {return (Gfo_fld_wtr)super.Ctor_xdat_base();}
public static Gfo_fld_wtr xowa_() {return new Gfo_fld_wtr().Ctor_xdat();}
}

View File

@@ -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.core.html.parsers; import gplx.*; import gplx.core.*; import gplx.core.html.*;
class Gfo_html_node {
public Gfo_html_node(byte[] src, int bgn, int end) {this.src = src; this.bgn = bgn; this.end = end;}
public byte[] Src() {return src;} private final byte[] src;
public int Bgn() {return bgn;} private final int bgn;
public int End() {return end;} private final int end;
}

View File

@@ -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.html.parsers; import gplx.*; import gplx.core.*; import gplx.core.html.*;
import gplx.core.btries.*; import gplx.core.primitives.*;
import gplx.xowa.*;
class Gfo_html_parser {
private final Gfo_msg_log msg_log = Gfo_msg_log.Test();
private final Xop_xatr_parser xatr_parser = new Xop_xatr_parser();
public void Parse(Gfo_html_wkr handler, byte[] src, int bgn, int end) {
// int src_len = src.length;
// int prv_pos = 0;
// int css_find_bgn_len = Css_find_bgn.length;
// byte[] protocol_prefix_bry = Bry_.new_u8(protocol_prefix);
// while (true) {
// int url_bgn = Bry_finder.Find_fwd(src, Css_find_bgn, prv_pos); if (url_bgn == Bry_.NotFound) break; // nothing left; stop
// url_bgn += css_find_bgn_len;
// int url_end = Bry_finder.Find_fwd(src, Byte_ascii.Quote, url_bgn, src_len); if (url_end == Bry_.NotFound) {usr_dlg.Warn_many("", "main_page.css_parse", "could not find css; pos='~{0}' text='~{1}'", url_bgn, String_.new_u8_by_len(src, url_bgn, url_bgn + 32)); break;}
// byte[] css_url_bry = Bry_.Mid(src, url_bgn, url_end);
// css_url_bry = Bry_.Replace(css_url_bry, Css_amp_find, Css_amp_repl); // &amp; -> &
// css_url_bry = url_encoder.Decode(css_url_bry); // %2C -> %7C -> |
// css_url_bry = Bry_.Add(protocol_prefix_bry, css_url_bry);
// rv.Add(String_.new_u8(css_url_bry));
// prv_pos = url_end;
// }
// return rv.XtoStrAry();
int src_len = src.length; int pos = 0;
while (pos < src_len) {
byte b = src[pos];
switch (b) {
case Byte_ascii.Angle_bgn:
pos = Parse_node(handler, src, end, pos, pos + 1);
break;
default:
++pos;
break;
}
}
}
private int Parse_node(Gfo_html_wkr handler, byte[] src, int end, int tkn_bgn, int tkn_end) {
int name_bgn = tkn_end;
int name_end = Bry_finder.Find_fwd_until_ws(src, name_bgn, end);
if (name_end == Bry_finder.Not_found) return end; // EOS; EX: "<abcEOS"
if (name_bgn == name_end) return tkn_end; // ws; EX: "< "
Object o = handler.Get_or_null(src, name_bgn, name_end);
if (o == null) return name_end; // unknown name: EX: "<unknown >"
int node_end = Bry_finder.Find_fwd(src, Byte_ascii.Angle_end, name_end, end);
if (node_end == Bry_finder.Not_found) return end; // EOS; EX: "<name lots_of_text_but_no_gt EOS"
Xop_xatr_itm[] xatr_ary = xatr_parser.Parse(msg_log, src, name_end, node_end);
Gfo_html_tkn tkn = (Gfo_html_tkn)o;
tkn.Process(src, Xop_xatr_hash.new_ary(src, xatr_ary));
return node_end;
}
}

View File

@@ -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.html.parsers; import gplx.*; import gplx.core.*; import gplx.core.html.*;
interface Gfo_html_wkr {
Gfo_html_tkn Get_or_null(byte[] src, int bgn, int end);
void Process(Gfo_html_node node);
}

View File

@@ -0,0 +1,33 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.core.html.parsers; import gplx.*; import gplx.core.*; import gplx.core.html.*;
import gplx.xowa.*;
interface Gfo_html_tkn {
int Tid();
byte[] Key();
void Process(byte[] src, Xop_xatr_hash hash);
}
class Gfo_html_tkn_ {
public static final int Tid_link = 1;
public static final byte[] Key_link = Bry_.new_a7("link");
}
class Gfo_html_tkn__link implements Gfo_html_tkn {
public int Tid() {return Gfo_html_tkn_.Tid_link;}
public byte[] Key() {return Gfo_html_tkn_.Key_link;}
@gplx.Virtual public void Process(byte[] src, Xop_xatr_hash hash) {}
}

View File

@@ -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.core.ints; import gplx.*; import gplx.core.*;
public class Int_ary_bldr {
public Int_ary_bldr(int len) {ary = new int[len];}
public Int_ary_bldr Set(int idx, int val) {ary[idx] = val; return this;}
public int[] Xto_int_ary() {return ary;} private int[] ary;
}

View File

@@ -0,0 +1,52 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.core.lists; import gplx.*; import gplx.core.*;
public class Binary_search_ {
public static int Search(CompareAble[] ary, int ary_len, CompareAble val) {
if (ary_len == 1) return 0;
int interval = ary_len / 2;
int pos = interval - List_adp_.Base1;
int pos_last = ary_len - 1;
int pos_prv = -1;
int loop_count = 0;
while (loop_count++ < 32) { // 32 bit integer
CompareAble lo = ary[pos];
CompareAble hi = pos + 1 == ary_len ? null : ary[pos + 1];
int adj = 0;
int lo_comp = val.compareTo(lo);
if (lo_comp == CompareAble_.Less) // val is < lo; search slots below
adj = -1;
else {
if (hi == null) return pos; // hi is null when at last slot in ary
int hi_comp = val.compareTo(hi);
if (hi_comp == CompareAble_.More) // val is > hi; search slots above
adj = 1;
else
return pos; // val is > lo and < hi; return slot
}
interval /= 2;
if (interval == 0) interval = 1; // do not allow 0 intervals; pos must always change;
pos += (interval * adj);
if (pos == 0 && pos_prv == 0) break; // NOTE: this will only happen when 1st member is not ""
if (pos < 0) pos = 0;
else if (pos > pos_last) pos = pos_last;
pos_prv = pos;
}
return Int_.MinValue; // should only occur if (a) ary's 0th slot is not ""; or (b) some unknown error
}
}

View File

@@ -0,0 +1,47 @@
/*
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.lists; import gplx.*; import gplx.core.*;
import org.junit.*; import gplx.core.primitives.*;
public class Binary_search__tst {
private Binary_search__fxt fxt = new Binary_search__fxt();
@Test public void Basic() {
fxt.Init_ary("", "e", "j", "o", "t", "y");
fxt.Test_binary_search("a", 0);
fxt.Test_binary_search("f", 1);
fxt.Test_binary_search("k", 2);
fxt.Test_binary_search("p", 3);
fxt.Test_binary_search("u", 4);
fxt.Test_binary_search("z", 5);
}
@Test public void One() {
fxt.Init_ary("");
fxt.Test_binary_search("a", 0);
}
}
class Binary_search__fxt {
public void Init_ary(String... v) {
int ary_len = v.length;
ary = new String_obj_val[ary_len];
for (int i = 0; i < ary_len; i++)
ary[i] = String_obj_val.new_(v[i]);
} private String_obj_val[] ary;
public void Test_binary_search(String val, int expd) {
int actl = Binary_search_.Search(ary, ary.length, String_obj_val.new_(val));
Tfds.Eq(expd, actl, val);
}
}

View File

@@ -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.core.net; import gplx.*; import gplx.core.*;
public interface Http_client_rdr {
void Stream_(Object o);
String Read_line();
byte[] Read_line_as_bry();
void Rls();
}

View File

@@ -0,0 +1,35 @@
/*
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.net; import gplx.*; import gplx.core.*;
public class Http_client_rdr_ {
public static Http_client_rdr new_stream() {return new Http_client_rdr__stream();}
public static Http_client_rdr new_mem() {return new Http_client_rdr__mem();}
}
class Http_client_rdr__mem implements Http_client_rdr {
private String[] ary; private int ary_len; private int idx;
public void Stream_(Object o) {
this.ary = (String[])o;
this.ary_len = ary.length;
this.idx = 0;
}
public String Read_line() {
return idx == ary_len ? null : ary[idx++];
}
public byte[] Read_line_as_bry() {return Bry_.new_u8(Read_line());}
public void Rls() {}
}

View File

@@ -0,0 +1,34 @@
/*
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.net; import gplx.*; import gplx.core.*;
import java.io.*;
class Http_client_rdr__stream implements Http_client_rdr {
private BufferedReader br;
public void Stream_(Object o) {
this.br = new BufferedReader(new InputStreamReader((InputStream)o, java.nio.charset.Charset.forName("UTF-8")));
}
public String Read_line() {
try {return br.readLine();}
catch (IOException e) {throw Exc_.new_exc(e, "net", "Read_line failed");}
}
public byte[] Read_line_as_bry() {return Bry_.new_u8(Read_line());}
public void Rls() {
try {br.close();}
catch (IOException e) {throw Exc_.new_exc(e, "net", "Rls failed");}
}
}

View File

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

View File

@@ -0,0 +1,21 @@
/*
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.net; import gplx.*; import gplx.core.*;
public class Http_client_wtr_ {
public static Http_client_wtr new_stream() {return new Http_client_wtr__stream();}
}

View File

@@ -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.core.net; import gplx.*; import gplx.core.*;
import gplx.ios.*;
import java.io.*;
class Http_client_wtr__stream implements Http_client_wtr {
private final byte[] tmp_stream_bry = new byte[1024];
private DataOutputStream stream;
public void Stream_(Object o) {
this.stream = new DataOutputStream((OutputStream)o);
}
public void Write_bry(byte[] bry) {
try {stream.write(bry);}
catch (IOException e) {throw Exc_.new_exc(e, "net", "Write_bry failed");}
}
public void Write_str(String s) {
try {stream.writeBytes(s);}
catch (Exception e) {throw Exc_.new_exc(e, "net", "Write_str failed");}
}
public void Write_mid(byte[] bry, int bgn, int end) {
try {stream.write(bry, bgn, end - bgn);}
catch (IOException e) {throw Exc_.new_exc(e, "net", "Write_mid failed");}
}
public void Write_stream(Io_stream_rdr stream_rdr) {
synchronized (tmp_stream_bry) {
int read = 0;
while (true) {
read = stream_rdr.Read(tmp_stream_bry, 0, 1024);
if (read == -1) break;
Write_mid(tmp_stream_bry, 0, read);
}
}
}
public void Rls() {
try {stream.close();}
catch (IOException e) {throw Exc_.new_exc(e, "net", "Rls failed");}
}
}

View File

@@ -0,0 +1,27 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.core.net; import gplx.*; import gplx.core.*;
public class Http_post_data_hash {
private final Ordered_hash hash = Ordered_hash_.new_bry_();
public int Len() {return hash.Count();}
public Http_post_data_itm Get_at(int i) {return (Http_post_data_itm)hash.Get_at(i);}
public Http_post_data_itm Get_by(byte[] k) {return (Http_post_data_itm)hash.Get_by(k);}
public void Add(byte[] key, byte[] val) {
hash.Add(key, new Http_post_data_itm(key, val));
}
}

View File

@@ -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.core.net; import gplx.*; import gplx.core.*;
public class Http_post_data_itm {
public Http_post_data_itm(byte[] key, byte[] val) {this.key = key; this.val = val;}
public byte[] Key() {return key;} private final byte[] key;
public byte[] Val() {return val;} private final byte[] val;
}

View File

@@ -0,0 +1,81 @@
/*
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.net; import gplx.*; import gplx.core.*;
public class Http_request_itm {
public Http_request_itm(int type, byte[] url, byte[] protocol, byte[] host, byte[] user_agent
, byte[] accept, byte[] accept_language, byte[] accept_encoding, boolean dnt, byte[] x_requested_with, byte[] cookie, byte[] referer
, int content_length, byte[] content_type, byte[] content_type_boundary
, byte[] connection, byte[] pragma, byte[] cache_control
, Http_post_data_hash post_data_hash
) {
this.type = type; this.url = url; this.protocol = protocol; this.host = host; this.user_agent = user_agent;
this.accept = accept; this.accept_language = accept_language; this.accept_encoding = accept_encoding; this.dnt = dnt; this.x_requested_with = x_requested_with; this.cookie = cookie; this.referer = referer;
this.content_length = content_length; this.content_type = content_type; this.content_type_boundary = content_type_boundary;
this.connection = connection; this.pragma = pragma; this.cache_control = cache_control;
this.post_data_hash = post_data_hash;
}
public int Type() {return type;} private final int type;
public byte[] Url() {return url;} private final byte[] url;
public byte[] Protocol() {return protocol;} private final byte[] protocol;
public byte[] Host() {return host;} private final byte[] host;
public byte[] User_agent() {return user_agent;} private final byte[] user_agent;
public byte[] Accept() {return accept;} private final byte[] accept;
public byte[] Accept_language() {return accept_language;} private final byte[] accept_language;
public byte[] Accept_encoding() {return accept_encoding;} private final byte[] accept_encoding;
public boolean Dnt() {return dnt;} private final boolean dnt;
public byte[] X_requested_with() {return x_requested_with;} private byte[] x_requested_with;
public byte[] Cookie() {return cookie;} private final byte[] cookie;
public byte[] Referer() {return referer;} private final byte[] referer;
public int Content_length() {return content_length;} private final int content_length;
public byte[] Content_type() {return content_type;} private final byte[] content_type;
public byte[] Content_type_boundary() {return content_type_boundary;} private final byte[] content_type_boundary;
public byte[] Connection() {return connection;} private final byte[] connection;
public byte[] Pragma() {return pragma;} private final byte[] pragma;
public byte[] Cache_control() {return cache_control;} private final byte[] cache_control;
public Http_post_data_hash Post_data_hash() {return post_data_hash;} private final Http_post_data_hash post_data_hash;
public String To_str(Bry_bfr bfr) {
bfr .Add_kv_line("type" , type == Type_get ? "GET" : "POST")
.Add_kv_line("url" , url)
.Add_kv_line("protocol" , protocol)
.Add_kv_line("host" , host)
.Add_kv_line("user_agent" , user_agent)
.Add_kv_line("accept" , accept)
.Add_kv_line("accept_encoding" , accept_encoding)
.Add_kv_line("dnt" , dnt)
.Add_kv_line("x_requested_with" , x_requested_with)
.Add_kv_line("cookie" , cookie)
.Add_kv_line("referer" , referer)
.Add_kv_line("content_length" , content_length)
.Add_kv_line("content_type" , content_type)
.Add_kv_line("content_type_boundary" , content_type_boundary)
.Add_kv_line("connection" , connection)
.Add_kv_line("pragma" , pragma)
.Add_kv_line("cache_control" , cache_control)
;
if (post_data_hash != null) {
int len = post_data_hash.Len();
for (int i = 0; i < len; ++i) {
Http_post_data_itm itm = post_data_hash.Get_at(i);
bfr.Add_byte_repeat(Byte_ascii.Space, 2);
bfr.Add_kv_line(String_.new_u8(itm.Key()), itm.Val());
}
}
return bfr.Xto_str_and_clear();
}
public static final int Type_get = 1, Type_post = 2;
}

View File

@@ -0,0 +1,168 @@
/*
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.net; import gplx.*; import gplx.core.*;
import gplx.core.primitives.*; import gplx.core.btries.*;
public class Http_request_parser {
private boolean dnt;
private int type, content_length;
private byte[] url, protocol, host, user_agent, accept, accept_language, accept_encoding, x_requested_with, cookie, referer, content_type, content_type_boundary, connection, pragma, cache_control;
private Http_post_data_hash post_data_hash;
private final Bry_bfr tmp_bfr = Bry_bfr.new_(255);
private final Http_server_wtr server_wtr; private final boolean log;
public Http_request_parser(Http_server_wtr server_wtr, boolean log) {this.server_wtr = server_wtr; this.log = log;}
public void Clear() {
this.dnt = false;
this.type = this.content_length = 0;
this.url = this.protocol = this.host = this.user_agent = this.accept = this.accept_language = this.accept_encoding = this.x_requested_with = this.cookie
= this.referer = this.content_type = this.content_type_boundary = this.connection = this.pragma = this.cache_control = null;
this.post_data_hash = null;
}
public Http_request_itm Parse(Http_client_rdr rdr) {
this.Clear();
boolean reading_post_data = false; boolean post_nl_seen = false;
while (true) {
String line_str = rdr.Read_line(); if (line_str == null) break; // needed for TEST
if (log) server_wtr.Write_str_w_nl(line_str);
byte[] line = Bry_.new_u8(line_str);
int line_len = line.length;
if (line_len == 0) {
switch (type) {
case Http_request_itm.Type_get: break;
case Http_request_itm.Type_post:
if (reading_post_data || post_nl_seen) throw Exc_.new_("http.request.parser;invalid new line during post", "request", To_str());
post_nl_seen = true; // only allow one \n per POST
continue; // ignore line and get next
default: throw Exc_.new_unimplemented();
}
break; // only GET will reach this line; GET requests always end with blank line; stop;
}
if (content_type_boundary != null && Bry_.Has_at_bgn(line, content_type_boundary)) {
while (true) {
if (Bry_.Has_at_end(line, Tkn_content_type_boundary_end)) break; // last form_data pair will end with "--"; stop
line = Parse_content_type_boundary(rdr);
}
break; // assume form_data ends POST request
}
Object o = trie.Match_bgn(line, 0, line_len);
if (o == null) {
server_wtr.Write_str_w_nl(String_.Format("http.request.parser; unknown line; line={0} request={1}", line_str, To_str()));
continue;
}
int val_bgn = Bry_finder.Find_fwd_while_ws(line, trie.Match_pos(), line_len); // skip ws after key; EX: "Host: "
int tid = ((Int_obj_val)o).Val();
switch (tid) {
case Tid_get:
case Tid_post: Parse_type(tid, val_bgn, line, line_len); break;
case Tid_host: this.host = Bry_.Mid(line, val_bgn, line_len); break;
case Tid_user_agent: this.user_agent = Bry_.Mid(line, val_bgn, line_len); break;
case Tid_accept: this.accept = Bry_.Mid(line, val_bgn, line_len); break;
case Tid_accept_language: this.accept_language = Bry_.Mid(line, val_bgn, line_len); break;
case Tid_accept_encoding: this.accept_encoding = Bry_.Mid(line, val_bgn, line_len); break;
case Tid_dnt: this.dnt = line[val_bgn] == Byte_ascii.Num_1; break;
case Tid_x_requested_with: this.x_requested_with = Bry_.Mid(line, val_bgn, line_len); break;
case Tid_cookie: this.cookie = Bry_.Mid(line, val_bgn, line_len); break;
case Tid_referer: this.referer = Bry_.Mid(line, val_bgn, line_len); break;
case Tid_content_length: this.content_length = Bry_.Xto_int_or(line, val_bgn, line_len, -1); break;
case Tid_content_type: Parse_content_type(val_bgn, line, line_len); break;
case Tid_connection: this.connection = Bry_.Mid(line, val_bgn, line_len); break;
case Tid_pragma: this.pragma = Bry_.Mid(line, val_bgn, line_len); break;
case Tid_cache_control: this.cache_control = Bry_.Mid(line, val_bgn, line_len); break;
default: throw Exc_.new_unhandled(tid);
}
}
return Make_request_itm();
}
private void Parse_type(int tid, int val_bgn, byte[] line, int line_len) { // EX: "POST /xowa-cmd:exec_as_json HTTP/1.1"
int url_end = Bry_finder.Find_bwd(line, Byte_ascii.Space, line_len); if (url_end == Bry_finder.Not_found) throw Exc_.new_("invalid protocol", "line", line, "request", To_str());
switch (tid) {
case Tid_get : this.type = Http_request_itm.Type_get; break;
case Tid_post : this.type = Http_request_itm.Type_post; break;
default : throw Exc_.new_unimplemented();
}
this.url = Bry_.Mid(line, val_bgn, url_end);
this.protocol = Bry_.Mid(line, url_end + 1, line_len);
}
private void Parse_content_type(int val_bgn, byte[] line, int line_len) { // EX: Content-Type: multipart/form-data; boundary=---------------------------72432484930026
int boundary_bgn = Bry_finder.Find_fwd(line, Tkn_boundary, val_bgn, line_len); if (boundary_bgn == Bry_finder.Not_found) throw Exc_.new_("invalid content_type", "line", line, "request", To_str());
int content_type_end = Bry_finder.Find_bwd(line, Byte_ascii.Semic, boundary_bgn);
this.content_type = Bry_.Mid(line, val_bgn, content_type_end);
this.content_type_boundary = Bry_.Add(Tkn_content_type_boundary_end, Bry_.Mid(line, boundary_bgn += Tkn_boundary.length, line_len));
}
private Http_request_itm Make_request_itm() {
return new Http_request_itm(type, url, protocol, host, user_agent, accept, accept_language, accept_encoding, dnt, x_requested_with, cookie, referer, content_length, content_type, content_type_boundary, connection, pragma, cache_control, post_data_hash);
}
private byte[] Parse_content_type_boundary(Http_client_rdr rdr) {
if (post_data_hash == null) post_data_hash = new Http_post_data_hash();
byte[] line = Bry_.new_u8(rdr.Read_line()); // cur line is already known to be content_type_boundary; skip it
byte[] key = Parse_post_data_name(line);
String line_str = rdr.Read_line(); // blank-line
if (String_.Len_gt_0(line_str)) {throw Exc_.new_("http.request.parser; blank_line should follow content_type_boundary", "request", To_str());}
while (true) {
line = Bry_.new_u8(rdr.Read_line());
if (Bry_.Has_at_bgn(line, content_type_boundary)) break;
tmp_bfr.Add(line);
}
byte[] val = tmp_bfr.Xto_bry_and_clear();
post_data_hash.Add(key, val);
return line;
}
private byte[] Parse_post_data_name(byte[] line) { // EX: Content-Disposition: form-data; name="data"
int line_len = line.length;
int pos = Assert_tkn(line, 0, line_len, Tkn_content_disposition);
pos = Assert_tkn(line, pos, line_len, Tkn_form_data);
pos = Assert_tkn(line, pos, line_len, Tkn_name);
int name_end = line_len;
if (line[pos] == Byte_ascii.Quote) {
if (line[name_end - 1] != Byte_ascii.Quote) throw Exc_.new_("http.request.parser; invalid form at end", "line", line, "request", To_str());
++pos;
--name_end;
}
return Bry_.Mid(line, pos, name_end);
}
private int Assert_tkn(byte[] src, int src_pos, int src_len, byte[] tkn) {
int tkn_len = tkn.length;
if (!Bry_.Match(src, src_pos, src_pos + tkn_len, tkn)) throw Exc_.new_("http.request.parser; invalid form_data line", "tkn", tkn, "line", src, "request", To_str());
int rv = src_pos += tkn_len;
return Bry_finder.Find_fwd_while_ws(src, rv, src_len);
}
private String To_str() {return Make_request_itm().To_str(tmp_bfr);}
private static final int Tid_get = 1, Tid_post = 2, Tid_host = 3, Tid_user_agent = 4, Tid_accept = 5, Tid_accept_language = 6, Tid_accept_encoding = 7, Tid_dnt = 8
, Tid_x_requested_with = 9, Tid_cookie = 10, Tid_referer = 11, Tid_content_length = 12, Tid_content_type = 13, Tid_connection = 14, Tid_pragma = 15, Tid_cache_control = 16;
private static final Btrie_slim_mgr trie = Btrie_slim_mgr.ci_ascii_()
.Add_str_int("GET" , Tid_get)
.Add_str_int("POST" , Tid_post)
.Add_str_int("Host:" , Tid_host)
.Add_str_int("User-Agent:" , Tid_user_agent)
.Add_str_int("Accept:" , Tid_accept)
.Add_str_int("Accept-Language:" , Tid_accept_language)
.Add_str_int("Accept-Encoding:" , Tid_accept_encoding)
.Add_str_int("DNT:" , Tid_dnt)
.Add_str_int("X-Requested-With:" , Tid_x_requested_with)
.Add_str_int("Cookie:" , Tid_cookie)
.Add_str_int("Referer:" , Tid_referer)
.Add_str_int("Content-length:" , Tid_content_length)
.Add_str_int("Content-Type:" , Tid_content_type)
.Add_str_int("Connection:" , Tid_connection)
.Add_str_int("Pragma:" , Tid_pragma)
.Add_str_int("Cache-Control:" , Tid_cache_control)
;
private static final byte[] Tkn_boundary = Bry_.new_a7("boundary="), Tkn_content_type_boundary_end = Bry_.new_a7("--")
, Tkn_content_disposition = Bry_.new_a7("Content-Disposition:"), Tkn_form_data = Bry_.new_a7("form-data;")
, Tkn_name = Bry_.new_a7("name=")
;
}

View File

@@ -0,0 +1,82 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.core.net; import gplx.*; import gplx.core.*;
import org.junit.*;
public class Http_request_parser_tst {
@Before public void init() {fxt.Clear();} private final Http_request_parser_fxt fxt = new Http_request_parser_fxt();
@Test public void Type_post() {
fxt.Test_type_post("POST /url HTTP/1.1", Http_request_itm.Type_post, "/url", "HTTP/1.1");
}
@Test public void Type_content_type() {
fxt.Test_content_type("Content-Type: multipart/form-data; boundary=---------------------------72432484930026", "multipart/form-data", "-----------------------------72432484930026");
}
@Test public void Type_form_data() {
fxt.Test_form_data(String_.Ary
( "POST /url HTTP/1.1"
, "Content-Type: multipart/form-data; boundary=---------------------------12345678901234"
, ""
, "-----------------------------12345678901234"
, "Content-Disposition: form-data; name=\"key0\""
, ""
, "val0"
, "-----------------------------12345678901234"
, "Content-Disposition: form-data; name=\"key1\""
, ""
, "val1"
, "-----------------------------12345678901234--"
)
, fxt.Make_post_data_itm("key0", "val0")
, fxt.Make_post_data_itm("key1", "val1")
);
}
}
class Http_request_parser_fxt {
private final Http_request_parser parser;
private final Http_client_rdr client_rdr = Http_client_rdr_.new_mem();
public Http_request_parser_fxt() {
this.parser = new Http_request_parser(Http_server_wtr_.Noop, false);
}
public void Clear() {
parser.Clear();
}
public Http_post_data_itm Make_post_data_itm(String key, String val) {return new Http_post_data_itm(Bry_.new_u8(key), Bry_.new_u8(val));}
public void Test_type_post(String line, int expd_type, String expd_url, String expd_protocol) {
client_rdr.Stream_(String_.Ary(line));
Http_request_itm req = parser.Parse(client_rdr);
Tfds.Eq(expd_type , req.Type());
Tfds.Eq(expd_url , String_.new_u8(req.Url()));
Tfds.Eq(expd_protocol , String_.new_u8(req.Protocol()));
}
public void Test_content_type(String line, String expd_content_type, String expd_content_boundary) {
client_rdr.Stream_(String_.Ary(line));
Http_request_itm req = parser.Parse(client_rdr);
Tfds.Eq(expd_content_type , String_.new_u8(req.Content_type()));
Tfds.Eq(expd_content_boundary , String_.new_u8(req.Content_type_boundary()));
}
public void Test_form_data(String[] ary, Http_post_data_itm... expd) {
client_rdr.Stream_(ary);
Http_request_itm req = parser.Parse(client_rdr);
Http_post_data_hash hash = req.Post_data_hash();
int len = hash.Len();
for (int i = 0; i < len; ++i) {
Http_post_data_itm itm = hash.Get_at(i);
Tfds.Eq_bry(itm.Key(), expd[i].Key());
Tfds.Eq_bry(itm.Val(), expd[i].Val());
}
}
}

View File

@@ -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.core.net; import gplx.*; import gplx.core.*;
public interface Http_server_wtr {
void Write_str_w_nl(String s);
}
class Http_server_wtr__noop implements Http_server_wtr {
public void Write_str_w_nl(String s) {}
}

View File

@@ -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.net; import gplx.*; import gplx.core.*;
public class Http_server_wtr_ {
public static Http_server_wtr new_console() {return new Http_server_wtr__console();}
public static final Http_server_wtr Noop = new Http_server_wtr__noop();
}

View File

@@ -0,0 +1,21 @@
/*
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.net; import gplx.*; import gplx.core.*;
class Http_server_wtr__console implements Http_server_wtr {
public void Write_str_w_nl(String s) {ConsoleAdp._.WriteLine(s);}
}

View File

@@ -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.core.net; import gplx.*; import gplx.core.*;
public interface Socket_adp {
Object Get_input_stream();
Object Get_output_stream();
void Rls();
}

View File

@@ -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.core.net; import gplx.*; import gplx.core.*;
import java.io.IOException;
import java.net.*;
public class Socket_adp__base implements Socket_adp {
private final Socket socket;
public Socket_adp__base(Socket socket) {this.socket = socket;}
public Object Get_input_stream() {
try {return socket.getInputStream();}
catch (IOException e) {throw Exc_.new_exc(e, "net", "Get_input_stream failed");}
}
public Object Get_output_stream() {
try {return socket.getOutputStream();}
catch (IOException e) {throw Exc_.new_exc(e, "net", "Get_output_stream failed");}
}
public void Rls() {
try {socket.close();}
catch (IOException e) {throw Exc_.new_exc(e, "net", "Rls failed");}
}
}

View File

@@ -0,0 +1,50 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.core.regxs; import gplx.*; import gplx.core.*;
public class Gfo_pattern {
private final Gfo_pattern_itm[] itms; private final int itms_len;
private final Gfo_pattern_ctx ctx = new Gfo_pattern_ctx();
public Gfo_pattern(byte[] raw) {
this.raw = raw;
itms = Gfo_pattern_itm_.Compile(raw);
itms_len = itms.length;
}
public byte[] Raw() {return raw;} private byte[] raw;
public boolean Match(byte[] val) {
int val_len = val.length;
int val_pos = 0;
ctx.Init(itms_len);
for (int i = 0; i < itms_len; ++i) {
Gfo_pattern_itm itm = itms[i];
ctx.Itm_idx_(i);
val_pos = itm.Match(ctx, val, val_len, val_pos);
if (!ctx.Rslt_pass()) return false;
}
return ctx.Rslt_pass() && val_pos == val_len;
}
public static Gfo_pattern[] Parse_to_ary(byte[] raw) {
byte[][] patterns = Bry_.Split(raw, Byte_ascii.Semic, true);
int patterns_len = patterns.length;
Gfo_pattern[] rv = new Gfo_pattern[patterns_len];
for (int i = 0; i < patterns_len; ++i) {
byte[] pattern = patterns[i];
rv[i] = new Gfo_pattern(pattern);
}
return rv;
}
}

View File

@@ -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.core.regxs; import gplx.*; import gplx.core.*;
public class Gfo_pattern_ctx {
public boolean Rslt_pass() {return rslt;} private boolean rslt;
public void Rslt_fail_() {rslt = false;}
public boolean Prv_was_wild() {return prv_was_wild;} public void Prv_was_wild_(boolean v) {prv_was_wild = v;} private boolean prv_was_wild;
private int itm_len;
public int Itm_idx() {return itm_idx;} public void Itm_idx_(int v) {itm_idx = v;} private int itm_idx;
public boolean Itm_idx_is_last() {return itm_idx == itm_len - 1;}
public void Init(int itm_len) {
this.rslt = true;
this.itm_len = itm_len;
this.prv_was_wild = false;
}
}

View File

@@ -0,0 +1,64 @@
/*
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.regxs; import gplx.*; import gplx.core.*;
import gplx.core.strings.*;
public interface Gfo_pattern_itm {
byte Tid();
void Compile(byte[] src, int bgn, int end);
int Match(Gfo_pattern_ctx ctx, byte[] src, int src_len, int pos);
void Xto_str(String_bldr sb);
}
class Gfo_pattern_itm_text implements Gfo_pattern_itm {
public Gfo_pattern_itm_text() {}
public byte Tid() {return Gfo_pattern_itm_.Tid_text;}
public byte[] Text() {return text;} private byte[] text; private int text_len;
public void Xto_str(String_bldr sb) {sb.Add(this.Tid()).Add("|" + String_.new_u8(text));}
public void Compile(byte[] src, int bgn, int end) {
this.text = Bry_.Mid(src, bgn, end);
this.text_len = end - bgn;
}
public int Match(Gfo_pattern_ctx ctx, byte[] src, int src_len, int pos) {
boolean pass = false;
int text_end = pos + text_len;
if (text_end > src_len) text_end = src_len;
if (ctx.Prv_was_wild()) {
int text_bgn = Bry_finder.Find_fwd(src, text, pos);
pass = text_bgn != Bry_finder.Not_found;
if (pass)
pos = text_bgn + text_len;
}
else {
pass = Bry_.Match(src, pos, text_end, text);
if (pass)
pos = text_end;
}
if (!pass) ctx.Rslt_fail_();
ctx.Prv_was_wild_(false);
return pos;
}
}
class Gfo_pattern_itm_wild implements Gfo_pattern_itm {
public byte Tid() {return Gfo_pattern_itm_.Tid_wild;}
public void Compile(byte[] src, int bgn, int end) {}
public int Match(Gfo_pattern_ctx ctx, byte[] src, int src_len, int pos) {
ctx.Prv_was_wild_(true);
return ctx.Itm_idx_is_last() ? src_len : pos;
}
public void Xto_str(String_bldr sb) {sb.Add(this.Tid()).Add("|*");}
public static final Gfo_pattern_itm_wild _ = new Gfo_pattern_itm_wild(); Gfo_pattern_itm_wild() {}
}

View File

@@ -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.regxs; import gplx.*; import gplx.core.*;
public class Gfo_pattern_itm_ {
public static final byte Tid_text = 0, Tid_wild = 1;
public static Gfo_pattern_itm[] Compile(byte[] raw) {
List_adp rv = List_adp_.new_();
int raw_len = raw.length;
int itm_bgn = -1;
Gfo_pattern_itm itm = null;
int pos = 0;
while (true) {
boolean last = pos == raw_len;
byte b = last ? Byte_ascii.Nil : raw[pos];
switch (b) {
case Byte_ascii.Nil:
if (itm != null) {itm.Compile(raw, itm_bgn, pos); itm = null; itm_bgn = -1;}
break;
case Byte_ascii.Star:
if (itm != null) {itm.Compile(raw, itm_bgn, pos); itm = null; itm_bgn = -1;}
rv.Add(Gfo_pattern_itm_wild._);
break;
default:
if (itm_bgn == -1) {
itm_bgn = pos;
itm = new Gfo_pattern_itm_text();
rv.Add(itm);
}
break;
}
++pos;
if (last) break;
}
return (Gfo_pattern_itm[])rv.To_ary_and_clear(Gfo_pattern_itm.class);
}
}

View File

@@ -0,0 +1,93 @@
/*
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.regxs; import gplx.*; import gplx.core.*;
import org.junit.*; import gplx.core.strings.*;
public class Gfo_pattern_tst {
@Before public void init() {fxt.Clear();} private Gfo_pattern_itm_fxt fxt = new Gfo_pattern_itm_fxt();
@Test public void Compile() {
fxt.Test_Compile("a" , fxt.itm_text_("a"));
fxt.Test_Compile("*" , fxt.itm_wild_());
fxt.Test_Compile("a*" , fxt.itm_text_("a"), fxt.itm_wild_());
fxt.Test_Compile("*a" , fxt.itm_wild_(), fxt.itm_text_("a"));
fxt.Test_Compile("*ab*" , fxt.itm_wild_(), fxt.itm_text_("ab"), fxt.itm_wild_());
fxt.Test_Compile("" );
}
@Test public void Match() {
Gfo_pattern pattern = fxt.pattern_("abc");
fxt.Test_Match_y(pattern, "abc");
fxt.Test_Match_n(pattern, "ab", "a", "bc", "Abc", "");
}
@Test public void Match_all() {
Gfo_pattern pattern = fxt.pattern_("*");
fxt.Test_Match_y(pattern, "a", "abc", "");
}
@Test public void Match_bgn() {
Gfo_pattern pattern = fxt.pattern_("abc*");
fxt.Test_Match_y(pattern, "abc", "abcdef");
fxt.Test_Match_n(pattern, "abd", "aabc", "");
}
@Test public void Match_end() {
Gfo_pattern pattern = fxt.pattern_("*abc");
fxt.Test_Match_y(pattern, "abc", "xyzabc");
fxt.Test_Match_n(pattern, "abcd", "");
}
@Test public void Match_mid() {
Gfo_pattern pattern = fxt.pattern_("a*c*e");
fxt.Test_Match_y(pattern, "ace", "abcde");
fxt.Test_Match_n(pattern, "abc", "");
}
@Test public void Bug_ctx() { // PURPOSE.fix: cb was true b/c ctx was not reset correctly
Gfo_pattern pattern = fxt.pattern_("b*");
fxt.Test_Match_y(pattern, "bc");
fxt.Test_Match_n(pattern, "cb");
}
}
class Gfo_pattern_itm_fxt {
public void Clear() {}
public Gfo_pattern pattern_(String raw) {return new Gfo_pattern(Bry_.new_u8(raw));}
public void Test_Match_y(Gfo_pattern pattern, String... itms) {Test_Match(pattern, itms, Bool_.Y);}
public void Test_Match_n(Gfo_pattern pattern, String... itms) {Test_Match(pattern, itms, Bool_.N);}
private void Test_Match(Gfo_pattern pattern, String[] itms, boolean expd) {
int len = itms.length;
for (int i = 0; i < len; i++) {
String itm = itms[i];
Tfds.Eq(expd, pattern.Match(Bry_.new_u8(itm)), "pattern={0} itm={1} expd={2}", String_.new_u8(pattern.Raw()), itm, expd);
}
}
public Gfo_pattern_itm_wild itm_wild_() {return Gfo_pattern_itm_wild._;}
public Gfo_pattern_itm_text itm_text_(String raw) {
Gfo_pattern_itm_text rv = new Gfo_pattern_itm_text();
byte[] bry = Bry_.new_u8(raw);
rv.Compile(bry, 0, bry.length);
return rv;
}
public void Test_Compile(String raw, Gfo_pattern_itm... expd) {
Gfo_pattern_itm[] actl = Gfo_pattern_itm_.Compile(Bry_.new_u8(raw));
Tfds.Eq(Ary_xto_str(expd), Ary_xto_str(actl));
}
private static String Ary_xto_str(Gfo_pattern_itm[] ary) {
int len = ary.length;
String_bldr sb = String_bldr_.new_();
for (int i = 0; i < len; i++) {
if (i != 0) sb.Add_char_nl();
Gfo_pattern_itm itm = ary[i];
itm.Xto_str(sb);
}
return sb.Xto_str_and_clear();
}
}

View File

@@ -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.core.threads; import gplx.*; import gplx.core.*;
public class Gfo_async_cmd_itm implements GfoInvkAble {
private GfoInvkAble invk; private String invk_key; private GfoMsg msg = GfoMsg_.new_cast_("");
public Gfo_async_cmd_itm Init(GfoInvkAble invk, String invk_key, Object... args) {
this.invk = invk; this.invk_key = invk_key;
msg.Args_reset();
msg.Clear();
int len = args.length;
for (int i = 0; i < len; i += 2) {
String key = (String)args[i];
Object val = args[i + 1];
msg.Add(key, val);
}
return this;
}
public void Exec() {
GfoInvkAble_.InvkCmd_msg(invk, invk_key, msg);
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_exec)) Exec();
else return GfoInvkAble_.Rv_unhandled;
return this;
} private static final String Invk_exec = "exec";
public static final Gfo_async_cmd_itm[] Ary_empty = new Gfo_async_cmd_itm[0];
}

View File

@@ -0,0 +1,34 @@
/*
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.threads; import gplx.*; import gplx.core.*;
class Gfo_async_cmd_mkr {
// private Gfo_async_cmd_itm[] free = Gfo_async_cmd_itm.Ary_empty, used = Gfo_async_cmd_itm.Ary_empty;
// private int free_bgn = 0, free_end = 0, ary_len = 0;
// public void Resize(int v) {
// free = (Gfo_async_cmd_itm[])Array_.Resize(free, v);
// used = (Gfo_async_cmd_itm[])Array_.Resize(used, v);
// ary_len = v;
// }
public Gfo_async_cmd_itm Get(GfoInvkAble invk, String invk_key, Object... args) {
Gfo_async_cmd_itm rv = new Gfo_async_cmd_itm();
rv.Init(invk, invk_key, args);
return rv;
}
public void Rls(Gfo_async_cmd_itm cmd) {
}
}

View File

@@ -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.threads; import gplx.*; import gplx.core.*;
import gplx.core.primitives.*;
public class Gfo_async_mgr implements GfoInvkAble {
private List_adp queue = List_adp_.new_();
private Bool_obj_ref running = Bool_obj_ref.n_();
private Gfo_async_cmd_mkr cmd_mkr = new Gfo_async_cmd_mkr();
public void Queue(GfoInvkAble invk, String invk_key, Object... args) {
Gfo_async_cmd_itm cmd = cmd_mkr.Get(invk, invk_key, args);
synchronized (queue) {
queue.Add(cmd);
}
synchronized (running) {
if (running.Val_n()) {
running.Val_y_();
gplx.core.threads.Thread_adp_.invk_(Invk_run, this, Invk_run).Start();
}
}
}
public void Run() {
Gfo_async_cmd_itm cmd = null;
try {
while (true) {
synchronized (queue) {
if (queue.Count() == 0) break;
cmd = (Gfo_async_cmd_itm)List_adp_.Pop(queue);
cmd.Exec();
}
}
}
finally {
synchronized (running) {
running.Val_n_();
}
}
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_run)) Run();
else return GfoInvkAble_.Rv_unhandled;
return this;
} private static final String Invk_run = "run";
}

View File

@@ -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.threads; import gplx.*; import gplx.core.*;
public interface Gfo_thread_cmd extends GfoInvkAble {
void Cmd_ctor();
String Async_key();
int Async_sleep_interval();
boolean Async_prog_enabled();
void Async_prog_run(int async_sleep_sum);
byte Async_init();
boolean Async_term();
void Async_run();
boolean Async_running();
Gfo_thread_cmd Async_next_cmd(); void Async_next_cmd_(Gfo_thread_cmd next);
}

View File

@@ -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.threads; import gplx.*; import gplx.core.*;
public class Gfo_thread_cmd_ {
public static final int Async_sleep_interval_1_second = 1000;
public static final byte Init_ok = 0, Init_cancel_step = 1, Init_cancel_all = 2;
}

View File

@@ -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.threads; import gplx.*; import gplx.core.*;
import gplx.gfui.*;
public class Gfo_thread_cmd_base implements Gfo_thread_cmd {
@gplx.Virtual public String Async_key() {return "undefined";}
public void Cmd_ctor() {}
public Gfo_thread_cmd_base Ctor(Gfo_usr_dlg usr_dlg, Gfui_kit kit) {this.usr_dlg = usr_dlg; this.kit = kit; return this;} protected Gfo_usr_dlg usr_dlg; protected Gfui_kit kit;
public GfoInvkAble Owner() {return owner;} public Gfo_thread_cmd_base Owner_(GfoInvkAble v) {owner = v; return this;} GfoInvkAble owner;
public Bry_fmtr_eval_mgr Url_eval_mgr() {return url_eval_mgr;} public Gfo_thread_cmd_base Url_eval_mgr_(Bry_fmtr_eval_mgr v) {url_eval_mgr = v; return this;} Bry_fmtr_eval_mgr url_eval_mgr;
public Gfo_thread_cmd Async_next_cmd() {return next_cmd;} public void Async_next_cmd_(Gfo_thread_cmd v) {next_cmd = v;} Gfo_thread_cmd next_cmd;
@gplx.Virtual public int Async_sleep_interval() {return Gfo_thread_cmd_.Async_sleep_interval_1_second;}
@gplx.Virtual public boolean Async_prog_enabled() {return false;}
@gplx.Virtual public byte Async_init() {return Gfo_thread_cmd_.Init_ok;}
@gplx.Virtual public boolean Async_term() {return true;}
@gplx.Virtual public void Async_prog_run(int async_sleep_sum) {}
@gplx.Virtual public void Async_bgn() {}
@gplx.Virtual public boolean Async_running() {return false;}
@gplx.Virtual public void Async_run() {}
@gplx.Virtual public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_owner)) return owner;
else if (ctx.Match(k, Invk_async_bgn)) Async_bgn();
else return GfoInvkAble_.Rv_unhandled;
return this;
} private static final String Invk_owner = "owner", Invk_async_bgn = "async_bgn";
}

View File

@@ -0,0 +1,73 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.core.threads; import gplx.*; import gplx.core.*;
import gplx.gfui.*;
public class Gfo_thread_cmd_download implements Gfo_thread_cmd {
public Gfo_thread_cmd Ctor(Gfo_usr_dlg usr_dlg, Gfui_kit kit) {this.usr_dlg = usr_dlg; this.kit = kit; xrg.Prog_dlg_(usr_dlg); return this;}
public Gfo_thread_cmd_download Init(String prog_fmt_hdr, String src, Io_url trg) {
this.src = src; this.trg = trg;
xrg.Prog_fmt_hdr_(prog_fmt_hdr).Init(src, trg);
return this;
} String src; protected Gfui_kit kit; Gfo_usr_dlg usr_dlg; Io_url trg;
public GfoInvkAble Owner() {return owner;} public Gfo_thread_cmd_download Owner_(GfoInvkAble v) {owner = v; return this;} GfoInvkAble owner;
public Bry_fmtr_eval_mgr Url_eval_mgr() {return url_eval_mgr;} public Gfo_thread_cmd_download Url_eval_mgr_(Bry_fmtr_eval_mgr v) {url_eval_mgr = v; return this;} Bry_fmtr_eval_mgr url_eval_mgr;
public void Cmd_ctor() {}
public Gfo_thread_cmd Async_next_cmd() {return next_cmd;} public void Async_next_cmd_(Gfo_thread_cmd v) {next_cmd = v;} Gfo_thread_cmd next_cmd;
@gplx.Virtual public String Async_key() {return KEY;}
public int Async_sleep_interval() {return Gfo_thread_cmd_.Async_sleep_interval_1_second;}
public boolean Async_prog_enabled() {return false;}
@gplx.Virtual public byte Async_init() {
if (Io_mgr.I.ExistsFil(trg)) {
int rslt = kit.Ask_yes_no_cancel(GRP_KEY, "target_exists", "Target file already exists: '~{0}'.\nDo you want to delete it?", trg.Raw());
switch (rslt) {
case Gfui_dlg_msg_.Btn_yes: Io_mgr.I.DeleteFil(trg); break;
case Gfui_dlg_msg_.Btn_no: return Gfo_thread_cmd_.Init_cancel_step;
case Gfui_dlg_msg_.Btn_cancel: return Gfo_thread_cmd_.Init_cancel_all;
default: throw Exc_.new_unhandled(rslt);
}
}
usr_dlg.Prog_many(GRP_KEY, "download.bgn", "contacting web server: '~{0}'", src); // update progress; some servers (like WMF dump servers) are slow to respond
return Gfo_thread_cmd_.Init_ok;
}
public boolean Async_term() {
usr_dlg.Prog_many(GRP_KEY, "clear", "");
return download_pass;
}
public void Async_prog_run(int async_sleep_sum) {}
public boolean Async_running() {return xrg.Prog_running();}
public void Async_run() {Thread_adp_.invk_(gplx.xowa.apps.Xoa_thread_.Key_bldr_download, this, Invk_async_bgn).Start();}
private void Download() {
download_pass = true;
if (!xrg.Exec()) {
xrg.Prog_running_(false);
download_pass = false;
kit.Ask_ok(GRP_KEY, "download.fail", "download failed. Please select 'read from file' if you've already downloaded a dump: url=~{0} error=~{1}", src, xrg.Rslt_err_str());
}
} boolean download_pass = true;
protected gplx.ios.IoEngine_xrg_downloadFil xrg = Io_mgr.I.DownloadFil_args("", Io_url_.Empty);
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_async_bgn)) Download();
else if (ctx.Match(k, Invk_owner)) return owner;
else if (ctx.Match(k, Invk_src_)) src = m.ReadStr("v");
else if (ctx.Match(k, Invk_trg_)) trg = Bry_fmtr_eval_mgr_.Eval_url(url_eval_mgr, m.ReadBry("v"));
else return GfoInvkAble_.Rv_unhandled;
return this;
} private static final String Invk_async_bgn = "async_bgn", Invk_owner = "owner", Invk_src_ = "src_", Invk_trg_ = "trg_";
static final String GRP_KEY = "gfo.thread.file.download";
public static final String KEY = "file.download";
}

View File

@@ -0,0 +1,61 @@
/*
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.threads; import gplx.*; import gplx.core.*;
import gplx.gfui.*;
public class Gfo_thread_cmd_replace implements Gfo_thread_cmd {
public Gfo_thread_cmd Init(Gfo_usr_dlg usr_dlg, Gfui_kit kit, Io_url fil) {
this.usr_dlg = usr_dlg; this.kit = kit; this.fil = fil;
return this;
} Gfui_kit kit; Gfo_usr_dlg usr_dlg; Io_url fil;
public GfoInvkAble Owner() {return owner;} public Gfo_thread_cmd_replace Owner_(GfoInvkAble v) {owner = v; return this;} GfoInvkAble owner;
public Bry_fmtr_eval_mgr Url_eval_mgr() {return url_eval_mgr;} public Gfo_thread_cmd_replace Url_eval_mgr_(Bry_fmtr_eval_mgr v) {url_eval_mgr = v; return this;} Bry_fmtr_eval_mgr url_eval_mgr;
public String Async_key() {return KEY;}
public void Cmd_ctor() {}
public Gfo_thread_cmd Async_next_cmd() {return next_cmd;} public void Async_next_cmd_(Gfo_thread_cmd v) {next_cmd = v;} Gfo_thread_cmd next_cmd;
public int Async_sleep_interval() {return Gfo_thread_cmd_.Async_sleep_interval_1_second;}
public boolean Async_prog_enabled() {return false;}
@gplx.Virtual public byte Async_init() {
if (!Io_mgr.I.ExistsFil(fil)) {kit.Ask_ok(GRP_KEY, "file_missing", "File does not exist: '~{0}'", fil.Raw()); return Gfo_thread_cmd_.Init_cancel_step;}
return Gfo_thread_cmd_.Init_ok;
}
public boolean Async_term() {return true;}
public void Async_prog_run(int async_sleep_sum) {}
public boolean Async_running() {return false;}
@gplx.Virtual public void Async_run() {Exec_find_replace();} // NOTE: do not run async; if multiple commands for same file then they will not always work
public void Exec_find_replace() {
String raw = Io_mgr.I.LoadFilStr(fil);
int pairs_len = pairs.Count();
for (int i = 0; i < pairs_len; i++) {
KeyVal kv = (KeyVal)pairs.Get_at(i);
raw = String_.Replace(raw, kv.Key(), kv.Val_to_str_or_null());
}
Io_mgr.I.SaveFilStr(fil, raw);
usr_dlg.Prog_many(GRP_KEY, "done", "replace completed: ~{0} ~{1}", fil.Raw(), pairs_len);
}
public List_adp pairs = List_adp_.new_();
@gplx.Virtual public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_async_bgn)) Exec_find_replace();
else if (ctx.Match(k, Invk_owner)) return owner;
else if (ctx.Match(k, Invk_fil_)) fil = Bry_fmtr_eval_mgr_.Eval_url(url_eval_mgr, m.ReadBry("v"));
else if (ctx.Match(k, Invk_add)) pairs.Add(KeyVal_.new_(m.ReadStr("find"), m.ReadStr("replace")));
else return GfoInvkAble_.Rv_unhandled;
return this;
} private static final String Invk_async_bgn = "async_bgn", Invk_owner = "owner", Invk_fil_ = "fil_", Invk_add = "add";
static final String GRP_KEY = "gfo.thread.file.download";
public static final String KEY = "text.replace";
}

View File

@@ -0,0 +1,115 @@
/*
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.threads; import gplx.*; import gplx.core.*;
import gplx.gfui.*; import gplx.xowa.bldrs.cmds.utils.*;
public class Gfo_thread_cmd_unzip implements Gfo_thread_cmd {
public Gfo_thread_cmd_unzip Init(Gfo_usr_dlg usr_dlg, Gfui_kit kit, ProcessAdp bzip2_process, ProcessAdp zip_process, ProcessAdp gz_process, Io_url src, Io_url trg) {
this.src = src; this.trg = trg; this.kit = kit; this.usr_dlg = usr_dlg;
unzip_wkr = new Xob_unzip_wkr().Init(bzip2_process, zip_process, gz_process).Process_run_mode_(ProcessAdp.Run_mode_async);
return this;
} private Io_url src, trg; private Gfui_kit kit; private Gfo_usr_dlg usr_dlg; private Xob_unzip_wkr unzip_wkr;
public GfoInvkAble Owner() {return owner;} public Gfo_thread_cmd_unzip Owner_(GfoInvkAble v) {owner = v; return this;} GfoInvkAble owner;
public void Cmd_ctor() {}
@gplx.Virtual public String Async_key() {return KEY;}
public Gfo_thread_cmd Async_next_cmd() {return next_cmd;} public void Async_next_cmd_(Gfo_thread_cmd v) {next_cmd = v;} Gfo_thread_cmd next_cmd;
public Bry_fmtr_eval_mgr Url_eval_mgr() {return url_eval_mgr;} public Gfo_thread_cmd_unzip Url_eval_mgr_(Bry_fmtr_eval_mgr v) {url_eval_mgr = v; return this;} Bry_fmtr_eval_mgr url_eval_mgr;
public int Async_sleep_interval() {return Gfo_thread_cmd_.Async_sleep_interval_1_second;}
public boolean Async_prog_enabled() {return true;}
public void Async_prog_run(int async_sleep_sum) {
String size_str = " please wait...";
if (trg.Type_fil()) size_str = gplx.ios.Io_size_.To_str(Io_mgr.I.QueryFil(trg).Size());
usr_dlg.Prog_many(GRP_KEY, "unzip", "unzipping: ~{0}", size_str);
}
@gplx.Virtual public byte Async_init() {
if (!Io_mgr.I.ExistsFil(src)) {
kit.Ask_ok(GRP_KEY, "source_missing", "Source file does not exist: '~{0}'", src.Raw());
return Gfo_thread_cmd_.Init_cancel_step;
}
trg_is_dir = trg.Type_dir();
if (delete_trg_if_exists
&& (( trg_is_dir && Io_mgr.I.ExistsDir(trg))
|| (!trg_is_dir && Io_mgr.I.ExistsFil(trg)))
) {
int rslt = kit.Ask_yes_no_cancel(GRP_KEY, "target_exists", "Target file already exists: '~{0}'.\nDo you want to delete it?", trg.Raw());
switch (rslt) {
case Gfui_dlg_msg_.Btn_yes: if (trg_is_dir) Io_mgr.I.DeleteDirDeep(trg); else Io_mgr.I.DeleteFil(trg); break;
case Gfui_dlg_msg_.Btn_no: return Gfo_thread_cmd_.Init_cancel_step;
case Gfui_dlg_msg_.Btn_cancel: return Gfo_thread_cmd_.Init_cancel_all;
}
}
return Gfo_thread_cmd_.Init_ok;
}
public boolean Async_running() {return unzip_wkr.Process_exit_code() == ProcessAdp.Exit_init;}
public void Async_run() {
usr_dlg.Prog_many(GRP_KEY, "bgn", "unzipping");
unzip_wkr.Decompress(src, trg);
}
public boolean Async_term() {
if (rename_dir) {
Io_url[] dirs = Io_mgr.I.QueryDir_args(trg.OwnerDir()).DirOnly_().Recur_(false).ExecAsUrlAry();
int dirs_len = dirs.length;
Io_url zip_dir = Io_url_.Empty;
for (int i = 0; i < dirs_len; i++) {
Io_url dir = dirs[i];
if (String_.Has_at_bgn(String_.Lower(dir.NameOnly()), String_.Lower(trg.NameOnly()))) { // HACK: check that directory starts with archive name; DATE:2013-12-22
zip_dir = dir;
break;
}
}
if (zip_dir == Io_url_.Empty) {
kit.Ask_ok(GRP_KEY, "rename.fail", "unable to find directory: trg=~{0}", trg.Raw());
return false;
}
if (!String_.Eq(String_.Lower(zip_dir.Raw()), String_.Lower(trg.Raw()))) // HACK: inkscape is itself
Io_mgr.I.MoveDirDeep(zip_dir, trg);
}
switch (term_cmd_for_src) {
case Term_cmd_for_src_noop: break;
case Term_cmd_for_src_delete: Io_mgr.I.DeleteFil(src); break;
case Term_cmd_for_src_move:
if (term_cmd_for_src_url == Io_url_.Empty) throw Exc_.new_("move specified, but no url");
Io_mgr.I.MoveFil_args(src, term_cmd_for_src_url, true).Exec();
break;
default: throw Exc_.new_unhandled(term_cmd_for_src);
}
usr_dlg.Prog_many(GRP_KEY, "done", "");
return true;
}
public static final byte Term_cmd_for_src_noop = 0, Term_cmd_for_src_delete = 1, Term_cmd_for_src_move = 2;
boolean rename_dir = false, trg_is_dir = false, delete_trg_if_exists = true;
public byte Term_cmd_for_src() {return term_cmd_for_src;} public void Term_cmd_for_src_(byte v) {term_cmd_for_src = v;} private byte term_cmd_for_src = Term_cmd_for_src_delete;
public Io_url Term_cmd_for_src_url() {return term_cmd_for_src_url;} public void Term_cmd_for_src_url_(Io_url v) {this.term_cmd_for_src_url = v;} Io_url term_cmd_for_src_url = Io_url_.Empty;
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_owner)) return owner;
else if (ctx.Match(k, Invk_src_)) src = Bry_fmtr_eval_mgr_.Eval_url(url_eval_mgr, m.ReadBry("v"));
else if (ctx.Match(k, Invk_trg_)) trg = Bry_fmtr_eval_mgr_.Eval_url(url_eval_mgr, m.ReadBry("v"));
else if (ctx.Match(k, Invk_rename_dir_)) rename_dir = m.ReadYn("v");
else if (ctx.Match(k, Invk_delete_trg_if_exists_)) delete_trg_if_exists = m.ReadYn("v");
else if (ctx.Match(k, Invk_term_cmd_for_src_)) term_cmd_for_src = Term_cmd_for_src_parse_(m.ReadStr("v"));
else return GfoInvkAble_.Rv_unhandled;
return this;
} private static final String Invk_owner = "owner", Invk_src_ = "src_", Invk_trg_ = "trg_", Invk_rename_dir_ = "rename_dir_", Invk_delete_trg_if_exists_ = "delete_trg_if_exists_", Invk_term_cmd_for_src_ = "term_cmd_for_src_";
private static byte Term_cmd_for_src_parse_(String s) {
if (String_.Eq(s, "noop")) return Term_cmd_for_src_noop;
else if (String_.Eq(s, "delete")) return Term_cmd_for_src_delete;
else if (String_.Eq(s, "move")) return Term_cmd_for_src_move;
else throw Exc_.new_unhandled(s);
}
static final String GRP_KEY = "xowa.thread.file.unzip";
public static final String KEY = "file.unzip";
}

View File

@@ -0,0 +1,62 @@
/*
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.threads; import gplx.*; import gplx.core.*;
public class Gfo_thread_pool implements GfoInvkAble {
private Object thread_lock = new Object();
private List_adp queue = List_adp_.new_();
private GfoMsg run_msg = GfoMsg_.new_cast_(Invk_run_wkr);
private boolean running = false;
public Gfo_usr_dlg Usr_dlg() {return usr_dlg;} public Gfo_thread_pool Usr_dlg_(Gfo_usr_dlg v) {usr_dlg = v; return this;} private Gfo_usr_dlg usr_dlg = Gfo_usr_dlg_.Noop;
public void Clear() {synchronized (thread_lock) {queue.Clear(); running = false;}}
public Gfo_thread_pool Add_at_end(Gfo_thread_wkr wkr) {
synchronized (thread_lock) {queue.Add(wkr);}
return this;
}
public void Resume() {
synchronized (thread_lock) {
running = false;
}
this.Run();
}
public void Run() {
Gfo_thread_wkr wkr = null;
synchronized (thread_lock) {
if (running) return; // already running; discard run request and rely on running-wkr to call Run when done
int len = queue.Count(); if (len == 0) return; // nothing in list; occurs when last item calls Run when done
running = true;
wkr = (Gfo_thread_wkr)List_adp_.Pop_first(queue);
}
Thread_adp_.Run_invk_msg(wkr.Name(), this, run_msg.Clear().Add("v", wkr));
}
private void Run_wkr(Gfo_thread_wkr wkr) {
try {wkr.Exec();}
catch (Exception e) {
usr_dlg.Warn_many("", "", "uncaught exception while running thread; name=~{0} err=~{1}", wkr.Name(), Err_.Message_gplx_brief(e));
}
finally {
if (wkr.Resume())
this.Resume();
}
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_run_wkr)) Run_wkr((Gfo_thread_wkr)m.ReadObj("v"));
else return GfoInvkAble_.Rv_unhandled;
return this;
}
private static final String Invk_run_wkr = "run_wkr";
}

View File

@@ -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.core.threads; import gplx.*; import gplx.core.*;
public interface Gfo_thread_wkr {
String Name();
void Exec();
boolean Resume();
}

View File

@@ -0,0 +1,151 @@
/*
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.xmls; import gplx.*; import gplx.core.*;
public class Gfo_xml_wtr {
private final Bry_bfr bfr = Bry_bfr.reset_(255), txt_bfr = Bry_bfr.reset_(32);
private byte quote_byte = Byte_ascii.Apos;
private byte[] quote_escape = Bry_quote_1_escape;
private List_adp nde_stack = List_adp_.new_();
private Gfo_xml_nde nde_cur = null;
private int indent = 0;
public void Quote_(boolean apos) {
if (apos) {
this.quote_byte = Byte_ascii.Apos;
this.quote_escape = Bry_quote_1_escape;
}
else {
this.quote_byte = Byte_ascii.Quote;
this.quote_escape = Bry_quote_2_escape;
}
}
public Gfo_xml_wtr Nde_lhs_bgn_grp(String v) {return Nde_lhs_bgn(Bool_.Y, v);}
public Gfo_xml_wtr Nde_lhs_bgn_itm(String v) {return Nde_lhs_bgn(Bool_.N, v);}
private Gfo_xml_wtr Nde_lhs_bgn(boolean grp, String v) {
nde_cur = new Gfo_xml_nde(grp, v);
nde_stack.Add(nde_cur);
bfr.Add_byte_repeat(Byte_ascii.Space, indent);
bfr.Add_byte(Byte_ascii.Angle_bgn).Add_str_u8(v);
indent += 2;
return this;
}
public Gfo_xml_wtr Nde_lhs_end() {
bfr.Add_byte(Byte_ascii.Angle_end);
if (nde_cur.Grp()) bfr.Add_byte_nl();
return this;
}
public Gfo_xml_wtr Nde_lhs(String v) {return Nde_lhs(Bool_.Y, v);}
private Gfo_xml_wtr Nde_lhs(boolean grp, String v) {
this.Nde_lhs_bgn(grp, v);
this.Nde_lhs_end();
return this;
}
public Gfo_xml_wtr Nde_rhs() {
Gfo_xml_nde nde = (Gfo_xml_nde)List_adp_.Pop(nde_stack);
indent -= 2;
if (nde.Grp()) bfr.Add_byte_repeat(Byte_ascii.Space, indent);
bfr.Add(Bry_nde_rhs_bgn).Add_str_u8(nde.Name()).Add_byte(Byte_ascii.Angle_end); // EX: </node>
bfr.Add_byte_nl();
return this;
}
public Gfo_xml_wtr Nde_txt_str(String name, String text) {
this.Nde_lhs(Bool_.N, name);
this.Txt_str_u8(text);
this.Nde_rhs();
return this;
}
public Gfo_xml_wtr Nde_txt_bry(String name, byte[] text) {
this.Nde_lhs(Bool_.N, name);
this.Txt_bry(text);
this.Nde_rhs();
return this;
}
public Gfo_xml_wtr Nde_txt_int(String name, int text) {
this.Nde_lhs(Bool_.N, name);
this.Txt_bry(Int_.Xto_bry(text));
this.Nde_rhs();
return this;
}
public Gfo_xml_wtr Atr_bgn(String key) {
bfr.Add_byte_space().Add_str_u8(key).Add_byte(Byte_ascii.Eq).Add_byte(quote_byte);
return this;
}
public Gfo_xml_wtr Atr_val_str_a7(String v) {bfr.Add_str_a7(v); return this;}
public Gfo_xml_wtr Atr_val_str_u8(String v) {bfr.Add_str_u8 (v); return this;}
public Gfo_xml_wtr Atr_val_bry (byte[] v) {bfr.Add(v); return this;}
public Gfo_xml_wtr Atr_val_int (int v) {bfr.Add_int_variable(v); return this;}
public Gfo_xml_wtr Atr_end() {
bfr.Add_byte(quote_byte);
return this;
}
public Gfo_xml_wtr Atr_kv_int(String key, int val) {return Atr_kv_bry(key, Int_.Xto_bry(val));}
public Gfo_xml_wtr Atr_kv_str_a7(String key, String val) {return Atr_kv_bry(key, Bry_.new_a7(val));}
public Gfo_xml_wtr Atr_kv_str_u8(String key, String val) {return Atr_kv_bry(key, Bry_.new_u8(val));}
public Gfo_xml_wtr Atr_kv_bry(String key, byte[] val) {
bfr.Add_byte_space().Add_str_u8(key);
bfr.Add_byte(Byte_ascii.Eq);
Atr_val_quote(val);
return this;
}
private Gfo_xml_wtr Atr_val_quote(byte[] val_bry) {
bfr.Add_byte(quote_byte);
bfr.Add_bry_escape(quote_byte, quote_escape, val_bry, 0, val_bry.length);
bfr.Add_byte(quote_byte);
return this;
}
public Gfo_xml_wtr Txt_bry(byte[] txt) {
int len = txt.length;
boolean dirty = false;
for (int i = 0; i < len; ++i) {
byte[] escape = null;
byte b = txt[i];
switch (b) {
case Byte_ascii.Lt: escape = Bry_escape_lt; break;
case Byte_ascii.Gt: escape = Bry_escape_gt; break;
case Byte_ascii.Amp: escape = Bry_escape_amp; break;
default: break;
}
if (escape != null && !dirty) {
bfr.Add_mid(txt, 0, i);
dirty = true;
}
if (dirty) {
if (escape == null) bfr.Add_byte(b);
else bfr.Add(escape);
}
}
if (dirty) bfr.Add_bfr_and_clear(txt_bfr);
else bfr.Add(txt);
return this;
}
public Gfo_xml_wtr Txt_str_u8(String txt) {return Txt_bry(Bry_.new_u8(txt));}
public String Bld_str() {return bfr.Xto_str_and_clear();}
private static final byte[]
Bry_nde_rhs_bgn = Bry_.new_a7("</")
// , Bry_nde_inline = Bry_.new_a7("/>")
, Bry_quote_1_escape = Bry_.new_a7("&apos;")
, Bry_quote_2_escape = Bry_.new_a7("&quot;")
, Bry_escape_lt = Bry_.new_a7("&lt;")
, Bry_escape_gt = Bry_.new_a7("&gt;")
, Bry_escape_amp = Bry_.new_a7("&amp;")
;
}
class Gfo_xml_nde {
public Gfo_xml_nde(boolean grp, String name) {this.grp = grp; this.name = name;}
public boolean Grp() {return grp;} private final boolean grp;
public String Name() {return name;} private final String name;
}

View File

@@ -0,0 +1,81 @@
/*
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.xmls; import gplx.*; import gplx.core.*;
import org.junit.*;
public class Gfo_xml_wtr_tst {
private final Gfo_xml_wtr_fxt fxt = new Gfo_xml_wtr_fxt();
@Before public void init() {}
@Test public void Root() {
fxt.Wtr().Nde_lhs("a").Nde_rhs();
fxt.Test_bld("<a>", "</a>");
}
@Test public void Nest() {
fxt.Wtr()
.Nde_lhs("a")
. Nde_lhs("a_a")
. Nde_lhs("a_a_a")
. Nde_rhs()
. Nde_rhs()
.Nde_rhs()
;
fxt.Test_bld
( "<a>"
, " <a_a>"
, " <a_a_a>"
, " </a_a_a>"
, " </a_a>"
, "</a>"
);
}
@Test public void Atrs() {
fxt.Wtr()
.Nde_lhs_bgn_itm("a")
.Atr_kv_str_a7("b", "b1")
.Nde_lhs_end()
.Nde_rhs()
;
fxt.Test_bld("<a b='b1'></a>");
}
@Test public void Atrs_escape() {
fxt.Wtr()
.Nde_lhs_bgn_itm("a")
.Atr_kv_str_a7("b", "'\"<>&")
.Nde_lhs_end()
.Nde_rhs()
;
fxt.Test_bld("<a b='&apos;\"<>&'></a>");
}
@Test public void Nde_txt() {
fxt.Wtr()
.Nde_txt_str("a", "a123")
;
fxt.Test_bld("<a>a123</a>");
}
@Test public void Nde_txt_escape() {
fxt.Wtr()
.Nde_txt_str("a", "'\"<>&x")
;
fxt.Test_bld("<a>'\"&lt;&gt;&amp;x</a>");
}
}
class Gfo_xml_wtr_fxt {
public Gfo_xml_wtr Wtr() {return wtr;} private final Gfo_xml_wtr wtr = new Gfo_xml_wtr();
public void Test_bld(String... lines) {
Tfds.Eq_str_lines(String_.Concat_lines_nl_skip_last(lines), wtr.Bld_str());
}
}

View File

@@ -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.dbs; import gplx.*;
import gplx.dbs.engines.sqlite.*;
public class Db_attach_cmd {
private final boolean diff_db;
private final Db_conn conn; private final String attach_name; private final Io_url attach_url;
private final List_adp sql_list = List_adp_.new_();
Db_attach_cmd(Db_conn conn, String attach_name, Io_url attach_url) {
this.conn = conn; this.attach_name = attach_name; this.attach_url = attach_url;
Sqlite_conn_info conn_info = (Sqlite_conn_info)conn.Conn_info();
this.diff_db = !String_.Eq(conn_info.Url().Raw(), attach_url.Raw());
}
public Db_attach_cmd Add_fmt(String msg, String sql_fmt, Object... sql_args) {
String sql = String_.Format(sql_fmt, sql_args);
sql = String_.Replace(sql, "<attach_db>", diff_db ? attach_name + "." : ""); // replace <attach> with either "attach_db." or "";
sql_list.Add(new Db_exec_sql_by_attach_itm(msg, sql));
return this;
}
public void Exec() {
Gfo_usr_dlg usr_dlg = Gfo_usr_dlg_.I;
if (diff_db) conn.Env_db_attach(attach_name, attach_url);
conn.Txn_bgn(attach_name); // NOTE: BEGIN TRAN must occur after ATTACH else sqlite will throw error
int len = sql_list.Count();
for (int i = 0; i < len; ++i) {
Db_exec_sql_by_attach_itm itm = (Db_exec_sql_by_attach_itm)sql_list.Get_at(i);
usr_dlg.Plog_many("", "", itm.Msg());
conn.Exec_sql(itm.Sql());
}
conn.Txn_end();
if (diff_db) conn.Env_db_detach(attach_name);
}
public static Db_attach_cmd new_(Db_conn conn, String attach_name, Io_url attach_url) {return new Db_attach_cmd(conn, attach_name, attach_url);}
}
class Db_exec_sql_by_attach_itm {
public Db_exec_sql_by_attach_itm(String msg, String sql) {this.msg = msg; this.sql = sql;}
public String Msg() {return msg;} private final String msg;
public String Sql() {return sql;} private final String sql;
}

View File

@@ -0,0 +1,40 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.dbs; import gplx.*;
import gplx.dbs.engines.sqlite.*;
public class Db_attach_rdr {
private final boolean diff_db;
private final Db_conn conn; private final String attach_name; private final Io_url attach_url;
public Db_attach_rdr(Db_conn conn, String attach_name, Io_url attach_url) {
this.conn = conn; this.attach_name = attach_name; this.attach_url = attach_url;
Sqlite_conn_info conn_info = (Sqlite_conn_info)conn.Conn_info();
this.diff_db = !String_.Eq(conn_info.Url().Raw(), attach_url.Raw());
}
public void Attach() {
try {
if (diff_db) conn.Env_db_attach(attach_name, attach_url);
} catch (Exception e) {Exc_.Noop(e); Gfo_usr_dlg_.I.Warn_many("", "", "db:failed to attach db; name=~{0} url=~{1}", attach_name, attach_url.Raw());}
}
public Db_rdr Exec_as_rdr(String sql) {
sql = String_.Replace(sql, "<attach_db>", diff_db ? attach_name + "." : ""); // replace <attach> with either "attach_db." or "";
return conn.Exec_sql_as_rdr_v2(sql);
}
public void Detach() {
if (diff_db) conn.Env_db_detach(attach_name);
}
}

View File

@@ -0,0 +1,34 @@
/*
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.cfgs; import gplx.*; import gplx.dbs.*;
public class Db_cfg_hash {
private final String grp; private final Ordered_hash hash = Ordered_hash_.new_();
public Db_cfg_hash(String grp) {this.grp = grp;}
public int Len() {return hash.Count();}
public Db_cfg_itm Get_at(int i) {return (Db_cfg_itm)hash.Get_at(i);}
public Db_cfg_itm Get(String key) {
Db_cfg_itm rv = (Db_cfg_itm)hash.Get_by(key);
return rv == null ? Db_cfg_itm.Empty : rv;
}
public void Set(String key, String val) {hash.Del(key); Add(key, val);}
public void Add(String key, String val) {
if (hash.Has(key)) throw Exc_.new_("itm exists", "grp", grp, "key", key);
Db_cfg_itm itm = new Db_cfg_itm(grp, key, val);
hash.Add(key, itm);
}
}

View File

@@ -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.dbs.cfgs; import gplx.*; import gplx.dbs.*;
public class Db_cfg_itm {
public Db_cfg_itm(String grp, String key, String val) {this.grp = grp; this.key = key; this.val = val;}
public String Grp() {return grp;} private final String grp;
public String Key() {return key;} private final String key;
public String Val() {return val;} public Db_cfg_itm Val_(String v) {val = v; return this;} private String val;
public String To_str_or(String or) {return val == null ? or : val;}
public byte[] To_bry_or(byte[] or) {try {return val == null ? or : Bry_.new_u8(val) ;} catch (Exception e) {throw err_parse(e, Bry_.Cls_val_name);}}
public int To_int_or(int or) {try {return val == null ? or : Int_.parse_or_(val, or) ;} catch (Exception e) {throw err_parse(e, Int_.Cls_val_name);}}
public long To_long_or(long or) {try {return val == null ? or : Long_.parse_or_(val, or) ;} catch (Exception e) {throw err_parse(e, Long_.Cls_val_name);}}
public byte To_byte_or(byte or) {try {return val == null ? or : Byte_.parse_or_(val, or) ;} catch (Exception e) {throw err_parse(e, Byte_.Cls_val_name);}}
public boolean To_yn_or_n() {return To_yn_or(Bool_.N);}
public boolean To_yn_or(boolean or) {try {return val == null ? or : Yn.parse_by_char_or(val, or);} catch (Exception e) {throw err_parse(e, Bool_.Cls_val_name);}}
public DateAdp To_date_or(DateAdp or) {try {return val == null ? or : DateAdp_.parse_gplx(val) ;} catch (Exception e) {throw err_parse(e, DateAdp_.Cls_ref_name);}}
public Guid_adp To_guid_or(Guid_adp or) {try {return val == null ? or : Guid_adp_.parse_(val) ;} catch (Exception e) {throw err_parse(e, Guid_adp_.Cls_ref_name);}}
public boolean To_bool() {Fail_if_null(); try {return Yn.parse_(val) ;} catch (Exception e) {throw err_parse(e, Bool_.Cls_val_name);}}
public byte To_byte() {Fail_if_null(); try {return Byte_.parse_(val) ;} catch (Exception e) {throw err_parse(e, Byte_.Cls_val_name);}}
public int To_int() {Fail_if_null(); try {return Int_.parse_(val) ;} catch (Exception e) {throw err_parse(e, Int_.Cls_val_name);}}
public String To_str() {Fail_if_null(); return val;}
private void Fail_if_null() {if (val == null) throw Exc_.new_("cfg.val is empty", "grp", grp, "key", key); }
private Exc err_parse(Exception e, String type) {return Exc_.new_("cfg.val is not parseable", "grp", grp, "key", key, "val", val, "type", type).Stack_erase_1_();}
private static final String Grp_none = "";
public static Db_cfg_itm new_str (String key, String val) {return new Db_cfg_itm(Grp_none , key, val);}
public static Db_cfg_itm new_str (String grp, String key, String val) {return new Db_cfg_itm(grp , key, val);}
public static Db_cfg_itm new_bry (String key, byte[] val) {return new Db_cfg_itm(Grp_none , key, String_.new_u8(val));}
public static Db_cfg_itm new_bry (String grp, String key, byte[] val) {return new Db_cfg_itm(grp , key, String_.new_u8(val));}
public static Db_cfg_itm new_int (String key, int val) {return new Db_cfg_itm(Grp_none , key, Int_.Xto_str(val));}
public static Db_cfg_itm new_int (String grp, String key, int val) {return new Db_cfg_itm(grp , key, Int_.Xto_str(val));}
public static Db_cfg_itm new_long (String key, long val) {return new Db_cfg_itm(Grp_none , key, Long_.Xto_str(val));}
public static Db_cfg_itm new_long (String grp, String key, long val) {return new Db_cfg_itm(grp , key, Long_.Xto_str(val));}
public static Db_cfg_itm new_byte (String key, byte val) {return new Db_cfg_itm(Grp_none , key, Byte_.Xto_str(val));}
public static Db_cfg_itm new_byte (String grp, String key, byte val) {return new Db_cfg_itm(grp , key, Byte_.Xto_str(val));}
public static Db_cfg_itm new_yn (String key, boolean val) {return new Db_cfg_itm(Grp_none , key, Yn.Xto_str(val));}
public static Db_cfg_itm new_yn (String grp, String key, boolean val) {return new Db_cfg_itm(grp , key, Yn.Xto_str(val));}
public static Db_cfg_itm new_DateAdp (String key, DateAdp val) {return new Db_cfg_itm(Grp_none , key, val.XtoStr_fmt_yyyyMMdd_HHmmss());}
public static Db_cfg_itm new_DateAdp (String grp, String key, DateAdp val) {return new Db_cfg_itm(grp , key, val.XtoStr_fmt_yyyyMMdd_HHmmss());}
public static Db_cfg_itm new_guid (String key, Guid_adp val) {return new Db_cfg_itm(Grp_none , key, val.XtoStr());}
public static Db_cfg_itm new_guid (String grp, String key, Guid_adp val) {return new Db_cfg_itm(grp , key, val.XtoStr());}
public static final Db_cfg_itm Empty = new Db_cfg_itm("empty", "empty", null);
}

View File

@@ -0,0 +1,123 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.dbs.cfgs; import gplx.*; import gplx.dbs.*;
import gplx.core.primitives.*;
public class Db_cfg_tbl implements RlsAble {
private final String tbl_name; private final Db_meta_fld_list flds = Db_meta_fld_list.new_();
private final String fld_grp, fld_key, fld_val;
private Db_stmt stmt_insert, stmt_update, stmt_select;
public Db_conn Conn() {return conn;} private final Db_conn conn;
public Db_cfg_tbl(Db_conn conn, String tbl_name) {
this.conn = conn; this.tbl_name = tbl_name;
this.fld_grp = flds.Add_str("cfg_grp", 255);
this.fld_key = flds.Add_str("cfg_key", 255);
this.fld_val = flds.Add_str("cfg_val", 1024);
conn.Rls_reg(this);
}
public void Rls() {
stmt_insert = Db_stmt_.Rls(stmt_insert);
stmt_update = Db_stmt_.Rls(stmt_update);
stmt_select = Db_stmt_.Rls(stmt_select);
}
public void Create_tbl() {conn.Ddl_create_tbl(Db_meta_tbl.new_(tbl_name, flds, Db_meta_idx.new_unique_by_tbl(tbl_name, "main", fld_grp, fld_key, fld_val)));}
public void Delete_val(String grp, String key) {conn.Stmt_delete(tbl_name, fld_grp, fld_key).Crt_str(fld_grp, grp).Crt_str(fld_key, key).Exec_delete();}
public void Delete_grp(String grp) {conn.Stmt_delete(tbl_name, fld_grp).Crt_str(fld_grp, grp).Exec_delete();}
public void Delete_all() {conn.Stmt_delete(tbl_name, Db_meta_fld.Ary_empty).Exec_delete();}
public void Insert_yn (String grp, String key, boolean val) {Insert_str(grp, key, val ? "y" : "n");}
public void Insert_byte (String grp, String key, byte val) {Insert_str(grp, key, Byte_.Xto_str(val));}
public void Insert_int (String grp, String key, int val) {Insert_str(grp, key, Int_.Xto_str(val));}
public void Insert_long (String grp, String key, long val) {Insert_str(grp, key, Long_.Xto_str(val));}
public void Insert_date (String grp, String key, DateAdp val) {Insert_str(grp, key, val.XtoStr_fmt_yyyyMMdd_HHmmss());}
public void Insert_guid (String grp, String key, Guid_adp val) {Insert_str(grp, key, val.XtoStr());}
public void Insert_bry (String grp, String key, byte[] val) {Insert_str(grp, key, String_.new_u8(val));}
public void Insert_str (String grp, String key, String val) {
if (stmt_insert == null) stmt_insert = conn.Stmt_insert(tbl_name, flds);
try {
stmt_insert.Clear().Val_str(fld_grp, grp).Val_str(fld_key, key).Val_str(fld_val, val).Exec_insert();
} catch (Exception e) {throw Exc_.new_exc(e, "db", "db_cfg.insert failed", "grp", grp, "key", key, "val", val, "db", conn.Conn_info().Xto_api());}
}
public void Update_yn (String grp, String key, boolean val) {Update_str(grp, key, val ? "y" : "n");}
public void Update_byte (String grp, String key, byte val) {Update_str(grp, key, Byte_.Xto_str(val));}
public void Update_int (String grp, String key, int val) {Update_str(grp, key, Int_.Xto_str(val));}
public void Update_long (String grp, String key, long val) {Update_str(grp, key, Long_.Xto_str(val));}
public void Update_date (String grp, String key, DateAdp val) {Update_str(grp, key, val.XtoStr_fmt_yyyyMMdd_HHmmss());}
public void Update_guid (String grp, String key, Guid_adp val) {Update_str(grp, key, val.XtoStr());}
public void Update_bry (String grp, String key, byte[] val) {Update_str(grp, key, String_.new_u8(val));}
public void Update_str (String grp, String key, String val) {
if (stmt_update == null) stmt_update = conn.Stmt_update_exclude(tbl_name, flds, fld_grp, fld_key);
stmt_update.Clear().Val_str(fld_val, val).Crt_str(fld_grp, grp).Crt_str(fld_key, key).Exec_update();
}
public void Upsert_yn (String grp, String key, boolean val) {Upsert_str(grp, key, val ? "y" : "n");}
public void Upsert_int (String grp, String key, int val) {Upsert_str(grp, key, Int_.Xto_str(val));}
public void Upsert_str (String grp, String key, String val) {
String cur_val = this.Select_str_or(grp, key, null);
if (cur_val == null) this.Insert_str(grp, key, val);
else this.Update_str(grp, key, val);
}
public boolean Select_yn (String grp, String key) {String val = Select_str(grp, key); return Parse_yn (grp, key, val);}
public byte Select_byte (String grp, String key) {String val = Select_str(grp, key); return Parse_byte (grp, key, val);}
public int Select_int (String grp, String key) {String val = Select_str(grp, key); return Parse_int (grp, key, val);}
public long Select_long (String grp, String key) {String val = Select_str(grp, key); return Parse_long (grp, key, val);}
public byte[] Select_bry (String grp, String key) {String val = Select_str(grp, key); return Parse_bry (grp, key, val);}
public DateAdp Select_date (String grp, String key) {String val = Select_str(grp, key); return Parse_date (grp, key, val);}
public Guid_adp Select_guid (String grp, String key) {String val = Select_str(grp, key); return Parse_guid (grp, key, val);}
public boolean Select_yn_or (String grp, String key, boolean or) {String val = Select_str_or(grp, key, null) ; return val == null ? or : Parse_yn (grp, key, val);}
public byte Select_byte_or (String grp, String key, byte or) {String val = Select_str_or(grp, key, null) ; return val == null ? or : Parse_byte (grp, key, val);}
public int Select_int_or (String grp, String key, int or) {String val = Select_str_or(grp, key, null) ; return val == null ? or : Parse_int (grp, key, val);}
public long Select_long_or (String grp, String key, long or) {String val = Select_str_or(grp, key, null) ; return val == null ? or : Parse_long (grp, key, val);}
public byte[] Select_bry_or (String grp, String key, byte[] or) {String val = Select_str_or(grp, key, null) ; return val == null ? or : Parse_bry (grp, key, val);}
public DateAdp Select_date_or (String grp, String key, DateAdp or) {String val = Select_str_or(grp, key, null) ; return val == null ? or : Parse_date (grp, key, val);}
public Guid_adp Select_guid_or (String grp, String key, Guid_adp or) {String val = Select_str_or(grp, key, null) ; return val == null ? or : Parse_guid (grp, key, val);}
public String Select_str (String grp, String key) {
String rv = Select_str_or(grp, key, null); if (rv == null) throw Exc_.new_("cfg.missing", "grp", grp, "key", key);
return rv;
}
public String Select_str_or (String grp, String key, String or) {
if (stmt_select == null) stmt_select = conn.Stmt_select(tbl_name, String_.Ary(fld_val), fld_grp, fld_key);
Db_rdr rdr = stmt_select.Clear().Crt_str(fld_grp, grp).Crt_str(fld_key, key).Exec_select__rls_manual();
try {return rdr.Move_next() ? rdr.Read_str(fld_val) : or;} finally {rdr.Rls();}
}
public Db_cfg_hash Select_as_hash(String grp) {
Db_cfg_hash rv = new Db_cfg_hash(grp);
Db_rdr rdr = conn.Stmt_select(tbl_name, flds, fld_grp).Crt_str(fld_grp, grp).Exec_select__rls_auto();
try {
while (rdr.Move_next()) {
rv.Add(rdr.Read_str(fld_key), rdr.Read_str(fld_val));
}
}
finally {rdr.Rls();}
return rv;
}
// NOTE: Assert guarantees that a value exists in database and returns it (Select + Insert); (1) String val = Assert('grp', 'key', 'val'); (2) Update('grp', 'key', 'val2');
public boolean Assert_yn (String grp, String key, boolean or) {String val = Select_str_or(grp, key, null) ; if (val == null) {Insert_yn (grp, key, or); return or;} return Parse_yn (grp, key, val);}
public byte Assert_byte (String grp, String key, byte or) {String val = Select_str_or(grp, key, null) ; if (val == null) {Insert_byte (grp, key, or); return or;} return Parse_byte (grp, key, val);}
public int Assert_int (String grp, String key, int or) {String val = Select_str_or(grp, key, null) ; if (val == null) {Insert_int (grp, key, or); return or;} return Parse_int (grp, key, val);}
public long Assert_long (String grp, String key, long or) {String val = Select_str_or(grp, key, null) ; if (val == null) {Insert_long (grp, key, or); return or;} return Parse_long (grp, key, val);}
public byte[] Assert_bry (String grp, String key, byte[] or) {String val = Select_str_or(grp, key, null) ; if (val == null) {Insert_bry (grp, key, or); return or;} return Parse_bry (grp, key, val);}
public DateAdp Assert_date (String grp, String key, DateAdp or) {String val = Select_str_or(grp, key, null) ; if (val == null) {Insert_date (grp, key, or); return or;} return Parse_date (grp, key, val);}
public Guid_adp Assert_guid (String grp, String key, Guid_adp or) {String val = Select_str_or(grp, key, null) ; if (val == null) {Insert_guid (grp, key, or); return or;} return Parse_guid (grp, key, val);}
public String Assert_str (String grp, String key, String or) {String val = Select_str_or(grp, key, null) ; if (val == null) {Insert_str (grp, key, or); return or;} return val;}
private boolean Parse_yn (String grp, String key, String val) {try {return Yn.parse_(val) ;} catch (Exception e) {throw err_parse(e, grp, key, val, Bool_.Cls_val_name);}}
private byte Parse_byte (String grp, String key, String val) {try {return Byte_.parse_(val) ;} catch (Exception e) {throw err_parse(e, grp, key, val, Byte_.Cls_val_name);}}
private int Parse_int (String grp, String key, String val) {try {return Int_.parse_(val) ;} catch (Exception e) {throw err_parse(e, grp, key, val, Int_.Cls_val_name);}}
private long Parse_long (String grp, String key, String val) {try {return Long_.parse_(val) ;} catch (Exception e) {throw err_parse(e, grp, key, val, Long_.Cls_val_name);}}
private byte[] Parse_bry (String grp, String key, String val) {try {return Bry_.new_u8(val) ;} catch (Exception e) {throw err_parse(e, grp, key, val, Bry_.Cls_val_name);}}
private DateAdp Parse_date (String grp, String key, String val) {try {return DateAdp_.parse_gplx(val) ;} catch (Exception e) {throw err_parse(e, grp, key, val, DateAdp_.Cls_ref_name);}}
private Guid_adp Parse_guid (String grp, String key, String val) {try {return Guid_adp_.parse_(val) ;} catch (Exception e) {throw err_parse(e, grp, key, val, Guid_adp_.Cls_ref_name);}}
private Exc err_parse(Exception e, String grp, String key, String val, String type) {return Exc_.new_exc(e, "db", "cfg.val is not parseable", "grp", grp, "key", key, "val", val, "type", type);}
}

View File

@@ -0,0 +1,28 @@
/*
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.metas; import gplx.*; import gplx.dbs.*;
import gplx.dbs.metas.updates.*;
public class Schema_db_mgr {
public Schema_loader_mgr Loader() {return loader;} public void Loader_(Schema_loader_mgr v) {loader = v;} private Schema_loader_mgr loader;
public Schema_update_mgr Updater() {return updater;} private final Schema_update_mgr updater = new Schema_update_mgr();
public Meta_tbl_mgr Tbl_mgr() {return tbl_mgr;} private final Meta_tbl_mgr tbl_mgr = new Meta_tbl_mgr();
public void Init(Db_conn conn) {
loader.Load(this, conn);
updater.Update(this, conn);
}
}

View File

@@ -0,0 +1,21 @@
/*
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.metas; import gplx.*; import gplx.dbs.*;
public interface Schema_loader_mgr {
void Load(Schema_db_mgr db_mgr, Db_conn conn);
}

View File

@@ -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.dbs.metas; import gplx.*; import gplx.dbs.*;
import gplx.dbs.qrys.*;
public class Schema_loader_mgr_ {
public static final Schema_loader_mgr Null = new Schema_loader_mgr__null();
public static final Schema_loader_mgr Sqlite = new Schema_loader_mgr__sqlite();
}
class Schema_loader_mgr__null implements Schema_loader_mgr {
public void Load(Schema_db_mgr db_mgr, Db_conn conn) {}
}
class Schema_loader_mgr__sqlite implements Schema_loader_mgr {
public void Load(Schema_db_mgr db_mgr, Db_conn conn) {
Gfo_usr_dlg_.I.Log_many("", "", "db.schema.load.bgn: conn=~{0}", conn.Conn_info().Xto_api());
Meta_tbl_mgr tbl_mgr = db_mgr.Tbl_mgr();
Db_qry__select_in_tbl qry = Db_qry__select_in_tbl.new_("sqlite_master", String_.Ary_empty, String_.Ary("type", "name", "sql"), Db_qry__select_in_tbl.Order_by_null);
Db_rdr rdr = conn.Stmt_new(qry).Exec_select__rls_auto();
try {
while (rdr.Move_next()) {
String type_str = rdr.Read_str("type");
String name = rdr.Read_str("name");
String sql = rdr.Read_str("sql");
int type_int = Meta_itm_tid.Xto_int(type_str);
switch (type_int) {
case Meta_itm_tid.Tid_table:
Meta_tbl_itm tbl_itm = new Meta_tbl_itm(name, sql);
tbl_mgr.Add(tbl_itm);
break;
case Meta_itm_tid.Tid_index: break; // noop for now
default: throw Exc_.new_unhandled(type_str);
}
}
} finally {rdr.Rls();}
Gfo_usr_dlg_.I.Log_many("", "", "db.schema.load.end");
}
}

View File

@@ -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.dbs.metas.updates; import gplx.*; import gplx.dbs.*; import gplx.dbs.metas.*;
public interface Schema_update_cmd {
String Name();
boolean Exec_is_done();
void Exec(Schema_db_mgr mgr, Db_conn conn);
}

View File

@@ -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.dbs.metas.updates; import gplx.*; import gplx.dbs.*; import gplx.dbs.metas.*;
import gplx.dbs.engines.sqlite.*;
public class Schema_update_cmd_ {
public static Schema_update_cmd Make_tbl_create(String tbl_name, String tbl_sql, Db_idx_itm... tbl_idxs) {return new Schema_update_cmd__tbl_create(tbl_name, tbl_sql, tbl_idxs);}
}
class Schema_update_cmd__tbl_create implements Schema_update_cmd {
private final String tbl_sql; private final Db_idx_itm[] tbl_idxs;
public Schema_update_cmd__tbl_create(String tbl_name, String tbl_sql, Db_idx_itm... tbl_idxs) {
this.tbl_name = tbl_name; this.tbl_sql = tbl_sql; this.tbl_idxs = tbl_idxs;
}
public String Name() {return "schema.tbl.create." + tbl_name;} private final String tbl_name;
public boolean Exec_is_done() {return exec_is_done;} private boolean exec_is_done;
public void Exec(Schema_db_mgr db_mgr, Db_conn conn) {
if (db_mgr.Tbl_mgr().Has(tbl_name)) return;
Gfo_usr_dlg_.I.Log_many("", "", "schema.tbl.create: tbl=~{0}", tbl_name);
Sqlite_engine_.Tbl_create(conn, tbl_name, tbl_sql);
Sqlite_engine_.Idx_create(conn, tbl_idxs);
exec_is_done = true;
}
}

View File

@@ -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.dbs.metas.updates; import gplx.*; import gplx.dbs.*; import gplx.dbs.metas.*;
public class Schema_update_mgr {
private List_adp cmds = List_adp_.new_();
public void Add(Schema_update_cmd cmd) {cmds.Add(cmd);}
public void Update(Schema_db_mgr schema_mgr, Db_conn conn) {
int cmds_len = cmds.Count();
for (int i = 0; i < cmds_len; ++i) {
Schema_update_cmd cmd = (Schema_update_cmd)cmds.Get_at(i);
try {cmd.Exec(schema_mgr, conn);}
catch (Exception e) {
Gfo_usr_dlg_.I.Warn_many("", "", "failed to run update cmd; name=~{0} err=~{1}", cmd.Name(), Err_.Message_gplx_brief(e));
}
}
}
}

View File

@@ -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.dbs.metas.updates; import gplx.*; import gplx.dbs.*; import gplx.dbs.metas.*;
import org.junit.*; import gplx.dbs.*;
public class Schema_update_mgr_tst {
@Before public void init() {fxt.Clear();} private Schema_update_mgr_fxt fxt = new Schema_update_mgr_fxt();
@Test public void Create() {
fxt.Test_exec_y(new Schema_update_cmd__mock());
}
@Test public void Delete() {
fxt.Init_itm(Meta_itm_tid.Tid_table, Schema_update_cmd__mock.Tbl_name);
fxt.Test_exec_n(new Schema_update_cmd__mock());
}
}
class Schema_update_mgr_fxt {
private Schema_update_mgr update_mgr; private Schema_db_mgr db_mgr;
public void Clear() {
update_mgr = new Schema_update_mgr();
db_mgr = new Schema_db_mgr();
}
public void Init_itm(int tid, String name) {
db_mgr.Tbl_mgr().Add(new Meta_tbl_itm(name, "sql"));
}
public void Test_exec_y(Schema_update_cmd cmd) {Test_exec(cmd, Bool_.Y);}
public void Test_exec_n(Schema_update_cmd cmd) {Test_exec(cmd, Bool_.N);}
private void Test_exec(Schema_update_cmd cmd, boolean expd) {
update_mgr.Add(cmd);
update_mgr.Update(db_mgr, Db_conn_.Noop);
Tfds.Eq(expd, cmd.Exec_is_done());
}
}
class Schema_update_cmd__mock implements Schema_update_cmd {
public String Name() {return "xowa.user.cfg_regy.create";}
public boolean Exec_is_done() {return exec_is_done;} private boolean exec_is_done;
public void Exec(Schema_db_mgr mgr, Db_conn conn) {
if (mgr.Tbl_mgr().Has(Tbl_name)) return;
exec_is_done = true;
}
public static final String Tbl_name = "tbl_mock";
}

View File

@@ -0,0 +1,28 @@
/*
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.fsdb; import gplx.*;
import gplx.dbs.*; import gplx.dbs.cfgs.*;
public class Fsdb_db_file {
public Fsdb_db_file(Io_url url, Db_conn conn) {
this.url = url; this.conn = conn;
this.tbl__core_cfg = new Db_cfg_tbl(conn, "xowa_cfg");
}
public Io_url Url() {return url;} private final Io_url url;
public Db_conn Conn() {return conn;} private final Db_conn conn;
public Db_cfg_tbl Tbl__cfg() {return tbl__core_cfg;} private final Db_cfg_tbl tbl__core_cfg;
}

View File

@@ -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.fsdb; import gplx.*;
import gplx.dbs.*; import gplx.xowa.files.origs.*;
public interface Fsdb_db_mgr {
boolean File__schema_is_1();
boolean File__solo_file();
String File__cfg_tbl_name();
Xof_orig_tbl[] File__orig_tbl_ary();
Fsdb_db_file File__mnt_file();
Fsdb_db_file File__abc_file__at(int mnt_id);
Fsdb_db_file File__atr_file__at(int mnt_id);
Fsdb_db_file File__bin_file__at(int mnt_id, int bin_id, String file_name);
Fsdb_db_file File__bin_file__new(int mnt_id, String file_name);
}

View File

@@ -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.fsdb; import gplx.*;
import gplx.dbs.*; import gplx.xowa.*; import gplx.xowa.wikis.data.*; import gplx.fsdb.meta.*;
public class Fsdb_db_mgr_ {
public static Fsdb_db_mgr new_detect(Xow_wiki wiki, Io_url wiki_dir, Io_url file_dir) {
Gfo_usr_dlg usr_dlg = Xoa_app_.Usr_dlg();
Io_url url = file_dir.GenSubFil(Fsdb_db_mgr__v1.Mnt_name); // EX: /xowa/file/en.wikipedia.org/wiki.mnt.sqlite3
if (Db_conn_bldr.I.Exists(url)) { // NOTE: check v1 before v2; note that as of v2.5.4, v2 files are automatically created on new import; DATE:2015-06-09
usr_dlg.Log_many("", "", "fsdb.db_core.v1: url=~{0}", url.Raw());
usr_dlg.Log_many("", "", "fsdb.db_core.v1 exists: orig=~{0} abc=~{1} atr_a=~{2}, atr_b=~{3}"
, Db_conn_bldr.I.Exists(file_dir.GenSubFil(Fsdb_db_mgr__v1.Orig_name))
, Db_conn_bldr.I.Exists(file_dir.GenSubFil_nest(Fsm_mnt_tbl.Mnt_name_main, Fsdb_db_mgr__v1.Abc_name))
, Db_conn_bldr.I.Exists(file_dir.GenSubFil_nest(Fsm_mnt_tbl.Mnt_name_main, Fsdb_db_mgr__v1.Atr_name_v1a))
, Db_conn_bldr.I.Exists(file_dir.GenSubFil_nest(Fsm_mnt_tbl.Mnt_name_main, Fsdb_db_mgr__v1.Atr_name_v1b))
);
return new Fsdb_db_mgr__v1(file_dir);
}
String domain_str = wiki.Domain_str();
Fsdb_db_mgr rv = null;
rv = load_or_null(Xowd_db_layout.Itm_few, usr_dlg, wiki_dir, wiki, domain_str); if (rv != null) return rv;
rv = load_or_null(Xowd_db_layout.Itm_lot, usr_dlg, wiki_dir, wiki, domain_str); if (rv != null) return rv;
rv = load_or_null(Xowd_db_layout.Itm_all, usr_dlg, wiki_dir, wiki, domain_str); if (rv != null) return rv;
usr_dlg.Log_many("", "", "fsdb.db_core.none: wiki_dir=~{0} file_dir=~{1}", wiki_dir.Raw(), file_dir.Raw());
return null;
}
private static Fsdb_db_mgr load_or_null(Xowd_db_layout layout, Gfo_usr_dlg usr_dlg, Io_url wiki_dir, Xow_wiki wiki, String domain_str) {
Io_url main_core_url = wiki_dir.GenSubFil(Fsdb_db_mgr__v2_bldr.Main_core_name(layout, domain_str));
if (!Db_conn_bldr.I.Exists(main_core_url)) return null;
usr_dlg.Log_many("", "", "fsdb.db_core.v2: type=~{0} url=~{1}", layout.Name(), main_core_url.Raw());
Db_conn main_core_conn = Db_conn_bldr.I.Get(main_core_url);
Io_url user_core_url = wiki_dir.GenSubFil(Fsdb_db_mgr__v2_bldr.Make_user_name(domain_str));
if (!Db_conn_bldr.I.Exists(user_core_url)) // if user file does not exist, create it; needed b/c offline packages don't include file; DATE:2015-04-19
Fsdb_db_mgr__v2_bldr.I.Make_core_file_user(wiki, user_core_url, user_core_url.NameAndExt(), main_core_url.NameAndExt());
Db_conn user_core_conn = Db_conn_bldr.I.Get(user_core_url);
return new Fsdb_db_mgr__v2(Fsdb_db_mgr__v2.Cfg__layout_file__get(main_core_conn), wiki_dir, new Fsdb_db_file(main_core_url, main_core_conn), new Fsdb_db_file(user_core_url, user_core_conn));
}
}

View File

@@ -0,0 +1,113 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.fsdb; import gplx.*;
import gplx.dbs.*; import gplx.dbs.cfgs.*; import gplx.fsdb.meta.*; import gplx.fsdb.data.*; import gplx.xowa.files.origs.*;
public class Fsdb_db_mgr__v1 implements Fsdb_db_mgr {
private final Io_url file_dir;
private final Fsdb_db_file orig_file, mnt_file, abc_file__main, abc_file__user, atr_file__main, atr_file__user;
private final Xof_orig_tbl[] orig_tbl_ary;
private String bin_prefix__main = "fsdb.bin.", bin_prefix__user = "fsdb.bin.";
public Fsdb_db_mgr__v1(Io_url file_dir) {
this.file_dir = file_dir;
this.orig_file = get_db(file_dir.GenSubFil(Orig_name)); // EX: /xowa/enwiki/wiki.orig#00.sqlite3
this.mnt_file = get_db(file_dir.GenSubFil(Mnt_name)); // EX: /xowa/enwiki/wiki.mnt.sqlite3
this.abc_file__main = get_db(file_dir.GenSubFil_nest(Fsm_mnt_tbl.Mnt_name_main, Abc_name)); // EX: /xowa/enwiki/fsdb.main/fsdb.abc.sqlite3
this.atr_file__main = get_db(Get_atr_db_url(Bool_.Y, file_dir, Fsm_mnt_tbl.Mnt_name_main)); // EX: /xowa/enwiki/fsdb.main/fsdb.atr.00.sqlite3
if (Db_conn_bldr.I.Get(file_dir.GenSubFil_nest(Fsm_mnt_tbl.Mnt_name_user, Abc_name)) == null) // user doesn't exist; create; DATE:2015-04-20
Fsdb_db_mgr__v1_bldr.I.Make_core_dir(file_dir, Fsm_mnt_mgr.Mnt_idx_user, Fsm_mnt_tbl.Mnt_name_user);
this.abc_file__user = get_db(file_dir.GenSubFil_nest(Fsm_mnt_tbl.Mnt_name_user, Abc_name)); // EX: /xowa/enwiki/fsdb.user/fsdb.abc.sqlite3
this.atr_file__user = get_db(Get_atr_db_url(Bool_.N, file_dir, Fsm_mnt_tbl.Mnt_name_user)); // EX: /xowa/enwiki/fsdb.user/fsdb.atr.00.sqlite3
this.orig_tbl_ary = new Xof_orig_tbl[] {new Xof_orig_tbl(orig_file.Conn(), this.File__schema_is_1())};
}
public boolean File__schema_is_1() {return Bool_.Y;}
public boolean File__solo_file() {return Bool_.N;}
public String File__cfg_tbl_name() {return "fsdb_cfg";}
public Xof_orig_tbl[] File__orig_tbl_ary() {return orig_tbl_ary;}
public Fsdb_db_file File__mnt_file() {return mnt_file;}
public Fsdb_db_file File__abc_file__at(int mnt_id) {return mnt_id == Fsm_mnt_mgr.Mnt_idx_main ? abc_file__main : abc_file__user;}
public Fsdb_db_file File__atr_file__at(int mnt_id) {return mnt_id == Fsm_mnt_mgr.Mnt_idx_main ? atr_file__main : atr_file__user;}
public Fsdb_db_file File__bin_file__at(int mnt_id, int bin_id, String file_name) {
boolean mnt_is_main = mnt_id == Fsm_mnt_mgr.Mnt_idx_main;
String bin_name = (mnt_is_main ? bin_prefix__main : bin_prefix__user) + Int_.Xto_str_pad_bgn_zero(bin_id, 4) + ".sqlite3";
String mnt_name = mnt_is_main ? Fsm_mnt_tbl.Mnt_name_main : Fsm_mnt_tbl.Mnt_name_user;
Io_url url = file_dir.GenSubFil_nest(mnt_name, bin_name); // EX: /xowa/enwiki/fsdb.main/fsdb.bin.0000.sqlite3
Db_conn conn = Db_conn_bldr.I.Get(url);
if (conn == null) { // NOTE: handle wikis with missing bin files; EX:sv.w missing bin.0010; DATE:2015-07-04
gplx.xowa.Xoa_app_.Usr_dlg().Warn_many("", "", "fsdb.v1: missing db; db=~{0}", url.Raw());
return Fsdb_db_mgr__v1_bldr.I.new_db__bin(url);
}
else
return new Fsdb_db_file(url, conn);
}
public Fsdb_db_file File__bin_file__new(int mnt_id, String file_name) {
String mnt_name = mnt_id == Fsm_mnt_mgr.Mnt_idx_main ? Fsm_mnt_tbl.Mnt_name_main : Fsm_mnt_tbl.Mnt_name_user;
Io_url url = file_dir.GenSubFil_nest(mnt_name, file_name); // EX: /xowa/enwiki/fsdb.main/fsdb.bin.0000.sqlite3
Db_conn conn = Db_conn_bldr.I.New(url);
Fsd_bin_tbl bin_tbl = new Fsd_bin_tbl(conn, Bool_.Y); bin_tbl.Create_tbl();
return new Fsdb_db_file(url, conn);
}
private Io_url Get_atr_db_url(boolean main, Io_url file_dir, String mnt_name) {
Io_url rv = null;
rv = file_dir.GenSubFil_nest(mnt_name, Atr_name_v1a);
if (Io_mgr.I.ExistsFil(rv)) {
if (main)
bin_prefix__main = "fsdb.bin#";
else
bin_prefix__user = "fsdb.bin#";
return rv;
}
rv = file_dir.GenSubFil_nest(mnt_name, Atr_name_v1b); if (Io_mgr.I.ExistsFil(rv)) return rv;
throw Exc_.new_("could not find atr file", "dir", file_dir.Raw(), "mnt", mnt_name);
}
public static final String Orig_name = "wiki.orig#00.sqlite3", Mnt_name = "wiki.mnt.sqlite3", Abc_name = "fsdb.abc.sqlite3"
, Atr_name_v1a = "fsdb.atr#00.sqlite3", Atr_name_v1b = "fsdb.atr.00.sqlite3";
private static Fsdb_db_file get_db(Io_url file) {
Db_conn conn = Db_conn_bldr.I.Get(file);
if (conn == null) conn = Db_conn_.Noop;
return new Fsdb_db_file(file, conn);
}
}
class Fsdb_db_mgr__v1_bldr {
public void Make_core_dir(Io_url file_dir, int mnt_id, String mnt_name) {
boolean schema_is_1 = true;
Io_url mnt_dir = file_dir.GenSubDir(mnt_name);
// make abc_fil
Fsdb_db_file db_abc = new_db(mnt_dir.GenSubFil(Fsdb_db_mgr__v1.Abc_name));
Db_cfg_tbl cfg_tbl = new Db_cfg_tbl(db_abc.Conn(), "fsdb_cfg"); cfg_tbl.Create_tbl();
Fsm_mnt_mgr.Patch(cfg_tbl);
Fsm_atr_tbl dba_tbl = new Fsm_atr_tbl(db_abc.Conn(), schema_is_1); dba_tbl.Create_tbl();
dba_tbl.Insert(mnt_id, mnt_name);
Fsm_bin_tbl dbb_tbl = new Fsm_bin_tbl(db_abc.Conn(), schema_is_1, mnt_id); dbb_tbl.Create_tbl();
dbb_tbl.Insert(0, "fsdb.bin.0000.sqlite3");
// make atr_fil
Fsdb_db_file db_atr = new_db(mnt_dir.GenSubFil(Fsdb_db_mgr__v1.Atr_name_v1b)); // create atr database in v1b style; "fsdb.atr.00.sqlite3" not "fsdb.atr#00.sqlite3"
Fsd_dir_tbl dir_tbl = new Fsd_dir_tbl(db_atr.Conn(), schema_is_1); dir_tbl.Create_tbl();
Fsd_fil_tbl fil_tbl = new Fsd_fil_tbl(db_atr.Conn(), schema_is_1, mnt_id); fil_tbl.Create_tbl();
Fsd_thm_tbl thm_tbl = new Fsd_thm_tbl(db_atr.Conn(), schema_is_1, mnt_id, Bool_.Y); thm_tbl.Create_tbl();
// make bin_fil
new_db__bin(mnt_dir.GenSubFil("fsdb.bin.0000.sqlite3"));
}
private Fsdb_db_file new_db(Io_url url) {return new Fsdb_db_file(url, Db_conn_bldr.I.New(url));}
public Fsdb_db_file new_db__bin(Io_url url) {
Fsdb_db_file rv = new_db(url);
Fsd_bin_tbl bin_tbl = new Fsd_bin_tbl(rv.Conn(), true); // NOTE: schema_is_1 is always true b/c it is in Fsdb_db_mgr__v1_bldr
bin_tbl.Create_tbl();
return rv;
}
public static final Fsdb_db_mgr__v1_bldr I = new Fsdb_db_mgr__v1_bldr(); Fsdb_db_mgr__v1_bldr() {}
}

View File

@@ -0,0 +1,67 @@
/*
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.fsdb; import gplx.*;
import gplx.dbs.*; import gplx.dbs.cfgs.*; import gplx.fsdb.meta.*; import gplx.xowa.files.origs.*; import gplx.xowa.wikis.data.*;
public class Fsdb_db_mgr__v2 implements Fsdb_db_mgr {
private final Xowd_db_layout layout; private final Io_url wiki_dir;
private final Fsdb_db_file file_main_core, file_user_core;
private final Xof_orig_tbl[] orig_tbl_ary;
public Fsdb_db_mgr__v2(Xowd_db_layout layout, Io_url wiki_dir, Fsdb_db_file file_main_core, Fsdb_db_file file_user_core) {
this.layout = layout; this.wiki_dir = wiki_dir;
this.file_main_core = file_main_core; this.file_user_core = file_user_core;
this.orig_tbl_ary = new Xof_orig_tbl[]
{ new Xof_orig_tbl(file_main_core.Conn(), this.File__schema_is_1())
, new Xof_orig_tbl(file_user_core.Conn(), this.File__schema_is_1())
};
}
public boolean File__schema_is_1() {return Bool_.N;}
public boolean File__solo_file() {return layout.Tid_is_all_or_few();}
public String File__cfg_tbl_name() {return Cfg_tbl_name;}
public Xof_orig_tbl[] File__orig_tbl_ary() {return orig_tbl_ary;}
public Fsdb_db_file File__mnt_file() {return file_main_core;}
public Fsdb_db_file File__abc_file__at(int mnt_id) {return mnt_id == Fsm_mnt_mgr.Mnt_idx_main ? file_main_core: file_user_core;}
public Fsdb_db_file File__atr_file__at(int mnt_id) {return mnt_id == Fsm_mnt_mgr.Mnt_idx_main ? file_main_core: file_user_core;}
public Fsdb_db_file File__bin_file__at(int mnt_id, int bin_id, String file_name) {
if (mnt_id == Fsm_mnt_mgr.Mnt_idx_user) return file_user_core;
if (layout.Tid_is_all_or_few()) return file_main_core;
Io_url url = wiki_dir.GenSubFil(file_name);
Db_conn conn = Db_conn_bldr.I.Get(url);
if (conn == null) { // bin file deleted or not downloaded; use Noop Db_conn and continue; do not fail; DATE:2015-04-16
Gfo_usr_dlg_.I.Warn_many("", "", "fsdb.bin:file does not exist; url=~{0}", url);
conn = Db_conn_.Noop;
}
return new Fsdb_db_file(url, conn);
}
public Fsdb_db_file File__bin_file__new(int mnt_id, String file_name) {
if (mnt_id == Fsm_mnt_mgr.Mnt_idx_user) return Fsdb_db_mgr__v2_bldr.Make_bin_tbl(file_user_core);
if (layout.Tid_is_all_or_few()) return Fsdb_db_mgr__v2_bldr.Make_bin_tbl(file_main_core);
Io_url url = wiki_dir.GenSubFil(file_name);
Db_conn conn = Db_conn_bldr.I.New(url);
Db_cfg_tbl cfg_tbl = new Db_cfg_tbl(conn, Cfg_tbl_name); cfg_tbl.Create_tbl();
return Fsdb_db_mgr__v2_bldr.Make_bin_tbl(new Fsdb_db_file(url, conn));
}
public static final String Cfg_tbl_name = "xowa_cfg";
public static Xowd_db_layout Cfg__layout_file__get(Db_conn main_core_conn) {
Db_cfg_tbl cfg_tbl = new Db_cfg_tbl(main_core_conn, "xowa_cfg");
return Xowd_db_layout.get_(cfg_tbl.Select_str_or(gplx.xowa.wikis.Xow_cfg_consts.Grp__bldr_fsdb, Cfg_key__layout_file, Xowd_db_layout.Name_few));
}
public static void Cfg__layout_file__set(Db_cfg_tbl cfg_tbl, Xowd_db_layout v) {
cfg_tbl.Insert_str(gplx.xowa.wikis.Xow_cfg_consts.Grp__bldr_fsdb, Cfg_key__layout_file, v.Name());
}
private static final String Cfg_key__layout_file = "layout_file";
}

View File

@@ -0,0 +1,113 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.fsdb; import gplx.*;
import gplx.dbs.*; import gplx.dbs.cfgs.*; import gplx.fsdb.meta.*; import gplx.fsdb.data.*; import gplx.xowa.files.origs.*;
import gplx.xowa.*; import gplx.xowa.wikis.data.*; import gplx.xowa.bldrs.infos.*;
public class Fsdb_db_mgr__v2_bldr {
public Fsdb_db_mgr__v2 Get_or_make(Xow_wiki wiki, boolean delete_if_exists) { // NOTE: must check if file exists else imports with existing v2 dbs will fail; DATE:2015-05-23
Xowd_db_layout layout = wiki.Data__core_mgr().Props().Layout_file();
String domain_str = wiki.Domain_str();
Io_url wiki_dir = wiki.Fsys_mgr().Root_dir();
String main_core_name = Main_core_name(layout, domain_str);
String user_core_name = Make_user_name(domain_str);
Io_url main_core_url = wiki_dir.GenSubFil(main_core_name);
Io_url user_core_url = wiki_dir.GenSubFil(user_core_name);
if (delete_if_exists) {
Db_conn_bldr.I.Get_or_noop(main_core_url).Rls_conn();
Db_conn_bldr.I.Get_or_noop(user_core_url).Rls_conn();
Io_mgr.I.DeleteFil(main_core_url);
Io_mgr.I.DeleteFil(user_core_url);
}
Fsdb_db_file main_core_file = Io_mgr.I.ExistsFil(main_core_url) ? Load_core_file(main_core_url) : Make_core_file_main(wiki, main_core_url, main_core_name, layout);
Fsdb_db_file user_core_file = Io_mgr.I.ExistsFil(user_core_url) ? Load_core_file(user_core_url) : Make_core_file_user(wiki, user_core_url, user_core_name, main_core_name);
return new Fsdb_db_mgr__v2(layout, wiki_dir, main_core_file, user_core_file);
}
private Fsdb_db_file Load_core_file(Io_url url) {return new Fsdb_db_file(url, Db_conn_bldr.I.Get(url));}
private Fsdb_db_file Make_core_file_main(Xow_wiki wiki, Io_url main_core_url, String main_core_name, Xowd_db_layout layout) {
Db_conn conn = layout.Tid_is_all() ? Db_conn_bldr.I.Get(main_core_url) : Db_conn_bldr.I.New(main_core_url); // if all, use existing (assumes same file name); else, create new
conn.Txn_bgn();
Fsdb_db_file rv = Make_core_file(main_core_url, conn, schema_is_1, Fsm_mnt_mgr.Mnt_idx_main);
if (!layout.Tid_is_all()) // do not make cfg data if all
Make_cfg_data(wiki, main_core_name, rv, Main_core_tid(layout), -1);
Fsdb_db_mgr__v2.Cfg__layout_file__set(rv.Tbl__cfg(), layout);
conn.Txn_end();
return rv;
}
public Fsdb_db_file Make_core_file_user(Xow_wiki wiki, Io_url user_core_url, String user_file_name, String main_core_name) { // always create file; do not create mnt_tbl;
Db_conn conn = Db_conn_bldr.I.New(user_core_url);
conn.Txn_bgn();
Fsdb_db_file rv = Make_core_file(user_core_url, conn, schema_is_1, Fsm_mnt_mgr.Mnt_idx_user);
Fsm_bin_tbl dbb_tbl = new Fsm_bin_tbl(conn, schema_is_1, Fsm_mnt_mgr.Mnt_idx_user); dbb_tbl.Insert(0, user_file_name);
Make_bin_tbl(rv);
Make_cfg_data(wiki, main_core_name, rv, Xowd_db_file_.Tid_file_user, -1);
conn.Txn_end();
return rv;
}
private Fsdb_db_file Make_core_file(Io_url core_url, Db_conn core_conn, boolean schema_is_1, int mnt_id) {
Fsdb_db_file rv = new Fsdb_db_file(core_url, core_conn);
Db_cfg_tbl cfg_tbl = rv.Tbl__cfg();
cfg_tbl.Create_tbl();
Fsm_mnt_mgr.Patch(cfg_tbl);
Fsm_mnt_mgr.Patch_core(cfg_tbl);
Xof_orig_tbl orig_tbl = new Xof_orig_tbl(core_conn, schema_is_1); orig_tbl.Create_tbl();
if (mnt_id == Fsm_mnt_mgr.Mnt_idx_main) {
Fsm_mnt_tbl mnt_tbl = new Fsm_mnt_tbl(core_conn, schema_is_1); mnt_tbl.Create_tbl();
cfg_tbl.Insert_int("core", "mnt.insert_idx", Fsm_mnt_mgr.Mnt_idx_user);
}
Fsm_atr_tbl dba_tbl = new Fsm_atr_tbl(core_conn, schema_is_1); dba_tbl.Create_tbl();
dba_tbl.Insert(mnt_id, core_url.NameAndExt());
Fsm_bin_tbl dbb_tbl = new Fsm_bin_tbl(core_conn, schema_is_1, mnt_id); dbb_tbl.Create_tbl();
Fsd_dir_tbl dir_tbl = new Fsd_dir_tbl(core_conn, schema_is_1); dir_tbl.Create_tbl();
Fsd_fil_tbl fil_tbl = new Fsd_fil_tbl(core_conn, schema_is_1, mnt_id); fil_tbl.Create_tbl();
Fsd_thm_tbl thm_tbl = new Fsd_thm_tbl(core_conn, schema_is_1, mnt_id, Bool_.Y); thm_tbl.Create_tbl();
return rv;
}
public static Fsdb_db_file Make_bin_tbl(Fsdb_db_file file) {
Fsd_bin_tbl bin_tbl = new Fsd_bin_tbl(file.Conn(), schema_is_1); bin_tbl.Create_tbl();
return file;
}
public static String Main_core_name(Xowd_db_layout layout, String wiki_domain) {
switch (layout.Tid()) {
case Xowd_db_layout.Const_all: return Main_core_name_all(wiki_domain);
case Xowd_db_layout.Const_few: return Main_core_name_few(wiki_domain);
case Xowd_db_layout.Const_lot: return Main_core_name_lot(wiki_domain);
default: throw Exc_.new_unimplemented();
}
}
private static byte Main_core_tid(Xowd_db_layout layout) {
switch (layout.Tid()) {
case Xowd_db_layout.Const_all: return Xowd_db_file_.Tid_core;
case Xowd_db_layout.Const_few: return Xowd_db_file_.Tid_file_solo;
case Xowd_db_layout.Const_lot: return Xowd_db_file_.Tid_file_core;
default: throw Exc_.new_unimplemented();
}
}
public static void Make_cfg_data(Xow_wiki wiki, String file_core_name, Fsdb_db_file file, byte file_tid, int part_id) {
Db_cfg_tbl cfg_tbl = file.Tbl__cfg();
Xowd_db_file core_db = wiki.Data__core_mgr().Db__core();
core_db.Info_session().Save(cfg_tbl);
Xob_info_file info_file = new Xob_info_file(-1, Xowd_db_file_.To_key(file_tid), Xob_info_file.Ns_ids_empty, part_id, Guid_adp_.new_(), 2, file_core_name, file.Url().NameAndExt());
info_file.Save(cfg_tbl);
}
private static String Main_core_name_all(String wiki_domain) {return wiki_domain + ".xowa";} // EX: en.wikipedia.org.xowa
private static String Main_core_name_few(String wiki_domain) {return wiki_domain + "-file.xowa";} // EX: en.wikipedia.org-file.xowa
private static String Main_core_name_lot(String wiki_domain) {return wiki_domain + "-file-core.xowa";} // EX: en.wikipedia.org-file-core.xowa
public static String Make_user_name(String wiki_domain) {return wiki_domain + "-file-user.xowa";} // EX: en.wikipedia.org-file-user.xowa
private static final boolean schema_is_1 = false;
public static final Fsdb_db_mgr__v2_bldr I = new Fsdb_db_mgr__v2_bldr(); Fsdb_db_mgr__v2_bldr() {}
}

View File

@@ -0,0 +1,100 @@
/*
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.fsdb.data; import gplx.*; import gplx.fsdb.*;
import gplx.core.primitives.*;
import gplx.dbs.*; import gplx.ios.*;
import gplx.dbs.engines.sqlite.*;
public class Fsd_bin_tbl implements RlsAble {
private final String tbl_name = "fsdb_bin"; private final Db_meta_fld_list flds = Db_meta_fld_list.new_();
private final String fld_owner_id, fld_owner_tid, fld_part_id, fld_data_url, fld_data;
private Db_conn conn; private Db_stmt stmt_insert, stmt_select; private Bry_bfr tmp_bfr;
private final Bool_obj_ref saved_in_parts = Bool_obj_ref.n_();
public Fsd_bin_tbl(Db_conn conn, boolean schema_is_1) {
this.conn = conn;
fld_owner_id = flds.Add_int_pkey ("bin_owner_id");
fld_owner_tid = flds.Add_byte ("bin_owner_tid");
fld_part_id = flds.Add_int ("bin_part_id");
fld_data_url = flds.Add_str ("bin_data_url", 255);
fld_data = flds.Add_bry ("bin_data"); // mediumblob
conn.Rls_reg(this);
}
public void Rls() {
stmt_insert = Db_stmt_.Rls(stmt_insert);
stmt_select = Db_stmt_.Rls(stmt_select);
}
public void Create_tbl() {conn.Ddl_create_tbl(Db_meta_tbl.new_(tbl_name, flds));}
public void Insert_bgn() {conn.Txn_bgn(); stmt_insert = conn.Stmt_insert(tbl_name, flds);}
public void Insert_commit() {conn.Txn_sav();}
public void Insert_end() {conn.Txn_end(); stmt_insert = Db_stmt_.Rls(stmt_insert);}
public void Insert_rdr(int id, byte tid, long bin_len, Io_stream_rdr bin_rdr) {
if (stmt_insert == null) {
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);
stmt_insert.Clear()
.Val_int(fld_owner_id, id)
.Val_byte(fld_owner_tid, tid)
.Val_int(fld_part_id, Part_id_null)
.Val_str(fld_data_url, Data_url_null)
.Val_bry(fld_data, bin_ary)
.Exec_insert();
}
public Io_stream_rdr Select_as_rdr(int owner_id) {
byte[] rv = Select(owner_id, null);
return rv == null
? Io_stream_rdr_.Noop
: Io_stream_rdr_.mem_(rv);
}
public boolean Select_to_url(int owner_id, Io_url url) {
saved_in_parts.Val_n();
byte[] rv = Select(owner_id, url);
if (rv == null) return false;
if (saved_in_parts.Val_y()) return true;
Io_mgr.I.SaveFilBry(url, rv);
return true;
}
private byte[] Select(int owner_id, Io_url url) {
if (stmt_select == null) stmt_select = conn.Stmt_select(tbl_name, String_.Ary(fld_data), fld_owner_id);
Db_rdr rdr = stmt_select.Clear().Crt_int(fld_owner_id, owner_id).Exec_select__rls_manual();
try {
if (rdr.Move_next()) {
byte[] rv = null;
try {rv = rdr.Read_bry(fld_data);}
catch (Exception e) {
if ( Op_sys.Cur().Tid_is_drd()
&& url != null // called by Select_to_url
&& String_.Has(Err_.Message_lang(e), "get field slot from row") // get field slot from row 0 col 0 failed
) {
rdr.Save_bry_in_parts(url, tbl_name, fld_data, fld_owner_id, owner_id);
saved_in_parts.Val_y_();
}
}
return rv == null ? Bry_.Empty : rv; // NOTE: bug in v0.10.1 where .ogg would save as null; return Bry_.Empty instead, else java.io.ByteArrayInputStream would fail on null
}
else
return null;
}
finally {rdr.Rls();}
}
public static final byte Owner_tid_fil = 1, Owner_tid_thm = 2;
public static final int Bin_db_id_null = -1, Size_null = -1;
private static final int Part_id_null = -1;
private static final String Data_url_null = "";
}

View File

@@ -0,0 +1,27 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.fsdb.data; import gplx.*; import gplx.fsdb.*;
public class Fsd_dir_itm {
public Fsd_dir_itm(int dir_id, int owner, byte[] name) {this.dir_id = dir_id; this.owner = owner; this.name = name;}
public int Dir_id() {return dir_id;} private final int dir_id;
public int Owner() {return owner;} private final int owner;
public byte[] Name() {return name;} private final byte[] name;
public static final int Owner_root = 0;
public static final Fsd_dir_itm Null = null;
}

View File

@@ -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.fsdb.data; import gplx.*; import gplx.fsdb.*;
import gplx.dbs.*;
public class Fsd_dir_tbl implements RlsAble {
private final String tbl_name = "fsdb_dir"; private final Db_meta_fld_list flds = Db_meta_fld_list.new_();
private final String fld_id, fld_owner_id, fld_name;
private final Db_conn conn; private Db_stmt stmt_insert, stmt_update, stmt_select_by_name;
public Fsd_dir_tbl(Db_conn conn, boolean schema_is_1) {
this.conn = conn;
this.fld_id = flds.Add_int_pkey ("dir_id");
this.fld_owner_id = flds.Add_int ("dir_owner_id");
this.fld_name = flds.Add_str ("dir_name", 255);
conn.Rls_reg(this);
}
public void Rls() {
stmt_insert = Db_stmt_.Rls(stmt_insert);
stmt_update = Db_stmt_.Rls(stmt_update);
stmt_select_by_name = Db_stmt_.Rls(stmt_select_by_name);
}
public void Create_tbl() {
conn.Ddl_create_tbl
( Db_meta_tbl.new_(tbl_name, flds
, Db_meta_idx.new_normal_by_tbl(tbl_name, "name", fld_name, fld_owner_id, fld_id)));
}
public void Insert(int id, byte[] name, int owner_id) {
if (stmt_insert == null) stmt_insert = conn.Stmt_insert(tbl_name, flds);
stmt_insert.Clear()
.Val_int(fld_id, id)
.Val_int(fld_owner_id, owner_id)
.Val_bry_as_str(fld_name, name)
.Exec_insert();
}
public void Update(int id, byte[] name, int owner_id) {
if (stmt_update == null) stmt_update = conn.Stmt_update_exclude(tbl_name, flds, fld_id);
stmt_update.Clear()
.Val_int(fld_owner_id, owner_id)
.Val_bry_as_str(fld_name, name)
.Crt_int(fld_id, id)
.Exec_update();
}
public Fsd_dir_itm Select_or_null(byte[] name) {
if (stmt_select_by_name == null) stmt_select_by_name = conn.Stmt_select(tbl_name, flds, fld_name);
Db_rdr rdr = stmt_select_by_name.Clear().Crt_bry_as_str(fld_name, name).Exec_select__rls_manual();
try {
return rdr.Move_next()
? new Fsd_dir_itm(rdr.Read_int(fld_id), rdr.Read_int(fld_owner_id), name)
: Fsd_dir_itm.Null
;
}
finally {rdr.Rls();}
}
}

View File

@@ -0,0 +1,34 @@
/*
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.fsdb.data; import gplx.*; import gplx.fsdb.*;
public class Fsd_fil_itm {
public Fsd_fil_itm Ctor(int mnt_id, int dir_id, int fil_id, int bin_db_id, byte[] name, int ext_id) {
this.mnt_id = mnt_id; this.dir_id = dir_id; this.fil_id = fil_id; this.bin_db_id = bin_db_id; this.name = name; this.ext_id = ext_id;
return this;
}
public int Mnt_id() {return mnt_id;} private int mnt_id;
public int Fil_id() {return fil_id;} private int fil_id;
public int Dir_id() {return dir_id;} private int dir_id;
public int Bin_db_id() {return bin_db_id;} private int bin_db_id;
public byte[] Name() {return name;} private byte[] name;
public int Ext_id() {return ext_id;} private int ext_id;
public static final Fsd_fil_itm Null = null;
public static byte[] Gen_cache_key(Bry_bfr bfr, int dir_id, byte[] name) {
return bfr.Add_int_variable(dir_id).Add_byte_pipe().Add(name).Xto_bry_and_clear();
}
}

View File

@@ -0,0 +1,105 @@
/*
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.fsdb.data; import gplx.*; import gplx.fsdb.*;
import gplx.dbs.*; import gplx.dbs.qrys.*; import gplx.dbs.engines.sqlite.*;
public class Fsd_fil_tbl implements RlsAble {
private final String tbl_name = "fsdb_fil"; private final Db_meta_fld_list flds = Db_meta_fld_list.new_();
private final String fld_id, fld_owner_id, fld_name, fld_xtn_id, fld_ext_id, fld_size, fld_modified, fld_hash, fld_bin_db_id;
private final String idx_owner;
private Db_conn conn; private Db_stmt stmt_insert, stmt_update, stmt_select_by_name; private int mnt_id;
public Fsd_fil_tbl(Db_conn conn, boolean schema_is_1, int mnt_id) {
this.conn = conn; this.mnt_id = mnt_id;
this.fld_id = flds.Add_int_pkey ("fil_id");
this.fld_owner_id = flds.Add_int ("fil_owner_id");
this.fld_xtn_id = flds.Add_int ("fil_xtn_id");
this.fld_ext_id = flds.Add_int ("fil_ext_id");
this.fld_bin_db_id = flds.Add_int ("fil_bin_db_id"); // group ints at beginning of table
this.fld_name = flds.Add_str ("fil_name", 255);
this.fld_size = flds.Add_long ("fil_size");
this.fld_modified = flds.Add_str ("fil_modified", 14); // stored as yyyyMMddHHmmss
this.fld_hash = flds.Add_str ("fil_hash", 40);
this.idx_owner = Db_meta_idx.Bld_idx_name(tbl_name, "owner");
conn.Rls_reg(this);
}
public void Rls() {
stmt_insert = Db_stmt_.Rls(stmt_insert);
stmt_update = Db_stmt_.Rls(stmt_update);
stmt_select_by_name = Db_stmt_.Rls(stmt_select_by_name);
}
public void Create_tbl() {
conn.Ddl_create_tbl(Db_meta_tbl.new_(tbl_name, flds
, Db_meta_idx.new_unique_by_name(tbl_name, idx_owner, fld_owner_id, fld_name, fld_id)
));
}
public void Insert(int id, int owner_id, byte[] name, int xtn_id, int ext_id, long size, int bin_db_id) {
if (stmt_insert == null) stmt_insert = conn.Stmt_insert(tbl_name, flds);
stmt_insert.Clear()
.Val_int(fld_id, id)
.Val_int(fld_owner_id, owner_id)
.Val_int(fld_xtn_id, xtn_id)
.Val_int(fld_ext_id, ext_id)
.Val_int(fld_bin_db_id, bin_db_id)
.Val_bry_as_str(fld_name, name)
.Val_long(fld_size, size)
.Val_str(fld_modified, String_.Empty)
.Val_str(fld_hash, String_.Empty)
.Exec_insert();
}
public void Update(int id, int owner_id, byte[] name, int xtn_id, int ext_id, long size, int bin_db_id) {
if (stmt_update == null) stmt_update = conn.Stmt_update_exclude(tbl_name, flds, fld_id);
stmt_update.Clear()
.Val_int(fld_owner_id, owner_id)
.Val_int(fld_xtn_id, xtn_id)
.Val_int(fld_ext_id, ext_id)
.Val_int(fld_bin_db_id, bin_db_id)
.Val_bry_as_str(fld_name, name)
.Val_long(fld_size, size)
.Val_str(fld_modified, String_.Empty)
.Val_str(fld_hash, String_.Empty)
.Crt_int(fld_id, id)
.Exec_update();
}
public Fsd_fil_itm Select_or_null(int dir_id, byte[] fil_name) {
if (stmt_select_by_name == null) {
Db_qry__select_cmd qry = Db_qry__select_cmd.new_().From_(tbl_name).Cols_(flds.To_str_ary()).Where_(Db_crt_.eq_many_(fld_owner_id, fld_name)).Indexed_by_(idx_owner);
stmt_select_by_name = conn.Stmt_new(qry);
}
Db_rdr rdr = stmt_select_by_name.Clear()
.Crt_int(fld_owner_id, dir_id)
.Crt_bry_as_str(fld_name, fil_name)
.Exec_select__rls_manual();
try {
return rdr.Move_next() ? new_(mnt_id, rdr) : Fsd_fil_itm.Null;
}
finally {rdr.Rls();}
}
public void Select_all(Bry_bfr key_bfr, gplx.cache.Gfo_cache_mgr_bry cache) {
Db_rdr rdr = conn.Stmt_select(tbl_name, flds, Db_meta_fld.Ary_empty).Exec_select__rls_auto();
try {
while (rdr.Move_next()) {
Fsd_fil_itm fil = new_(mnt_id, rdr);
byte[] cache_key = Fsd_fil_itm.Gen_cache_key(key_bfr, fil.Dir_id(), fil.Name());
cache.Add(cache_key, fil);
}
}
finally {rdr.Rls();}
}
private Fsd_fil_itm new_(int mnt_id, Db_rdr rdr) {
return new Fsd_fil_itm().Ctor(mnt_id, rdr.Read_int(fld_owner_id), rdr.Read_int(fld_id), rdr.Read_int(fld_bin_db_id), rdr.Read_bry_by_str(fld_name), rdr.Read_int(fld_ext_id));
}
}

View File

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

View File

@@ -0,0 +1,61 @@
/*
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.fsdb.data; import gplx.*; import gplx.fsdb.*;
public class Fsd_thm_itm {
public void Ctor(int mnt_id, int dir_id, int fil_id, int thm_id, int bin_db_id, int w, int h, double time, int page, long size, String modified, String hash) {
this.mnt_id = mnt_id; this.dir_id = dir_id; this.fil_id = fil_id; this.thm_id = thm_id; this.bin_db_id = bin_db_id;
this.w = w; this.h = h; this.time = time; this.page = page;
this.size = size; this.modified = modified; this.hash = hash;
}
public int Mnt_id() {return mnt_id;} private int mnt_id;
public int Dir_id() {return dir_id;} private int dir_id;
public int Fil_id() {return fil_id;} private int fil_id;
public int Thm_id() {return thm_id;} private int thm_id;
public int Bin_db_id() {return bin_db_id;} private int bin_db_id;
public int W() {return w;} private int w;
public int H() {return h;} private int h;
public double Time() {return time;} private double time;
public int Page() {return page;} private int page;
public long Size() {return size;} private long size;
public String Modified() {return modified;} private String modified;
public String Hash() {return hash;} private String hash;
public int Req_w() {return req_w;} private int req_w;
public double Req_time() {return req_time;} private double req_time;
public int Req_page() {return req_page;} private int req_page;
public void Init_by_req(int w, double time, int page) {this.w = w; this.time = time; this.page = page;}
public void Init_by_match(Fsd_thm_itm comp) {
this.req_w = w; this.req_time = time; this.req_page = page;
this.mnt_id = comp.mnt_id; this.dir_id = comp.dir_id; this.fil_id = comp.fil_id; this.thm_id = comp.thm_id; this.bin_db_id = comp.bin_db_id;
this.w = comp.w; this.h = comp.h; this.time = comp.time; this.page = comp.page;
this.size = comp.size; this.modified = comp.modified; this.hash = comp.hash;
}
public static final Fsd_thm_itm Null = null;
public static final Fsd_thm_itm[] Ary_empty = new Fsd_thm_itm[0];
public static Fsd_thm_itm new_() {return new Fsd_thm_itm();} Fsd_thm_itm() {}
}
class Fsdb_thm_itm_sorter implements gplx.lists.ComparerAble {
public int compare(Object lhsObj, Object rhsObj) {
Fsd_thm_itm lhs = (Fsd_thm_itm)lhsObj;
Fsd_thm_itm rhs = (Fsd_thm_itm)rhsObj;
int comp = Int_.Compare (lhs.W() , rhs.W()); if (comp != CompareAble_.Same) return -comp; // sort by decreasing width
comp = Double_.Compare (lhs.Time() , rhs.Time()); if (comp != CompareAble_.Same) return comp; // sort by increasing time
return Int_.Compare (lhs.Page() , rhs.Page()); // sort by increasing page
}
public static final Fsdb_thm_itm_sorter I = new Fsdb_thm_itm_sorter(); Fsdb_thm_itm_sorter() {}
}

View File

@@ -0,0 +1,155 @@
/*
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.fsdb.data; import gplx.*; import gplx.fsdb.*;
import gplx.dbs.*; import gplx.fsdb.meta.*; import gplx.xowa.files.*;
public class Fsd_thm_tbl implements RlsAble {
private final String tbl_name; private final Db_meta_fld_list flds = Db_meta_fld_list.new_();
private final String fld_id, fld_owner_id, fld_w, fld_h, fld_time, fld_page, fld_bin_db_id, fld_size, fld_modified, fld_hash;
private final Db_conn conn; private Db_stmt stmt_insert, stmt_select_by_fil_exact, stmt_select_by_fil_near; private int mnt_id; private boolean schema_thm_page;
public Fsd_thm_tbl(Db_conn conn, boolean schema_is_1, int mnt_id, boolean schema_thm_page) {
this.conn = conn; this.mnt_id = mnt_id; this.schema_thm_page = schema_thm_page;
this.tbl_name = schema_is_1 ? "fsdb_xtn_thm" : "fsdb_thm";
this.fld_id = flds.Add_int_pkey ("thm_id");
this.fld_owner_id = flds.Add_int ("thm_owner_id");
this.fld_w = flds.Add_int ("thm_w");
this.fld_h = flds.Add_int ("thm_h");
if (schema_thm_page) {
this.fld_time = flds.Add_double ("thm_time");
this.fld_page = flds.Add_int ("thm_page");
}
else {
this.fld_time = flds.Add_int ("thm_thumbtime");
this.fld_page = Db_meta_fld.Key_null;
}
this.fld_bin_db_id = flds.Add_int ("thm_bin_db_id");
this.fld_size = flds.Add_long ("thm_size");
this.fld_modified = flds.Add_str ("thm_modified", 14); // stored as yyyyMMddHHmmss
this.fld_hash = flds.Add_str ("thm_hash", 40);
conn.Rls_reg(this);
}
public void Rls() {
stmt_insert = Db_stmt_.Rls(stmt_insert);
stmt_select_by_fil_exact = Db_stmt_.Rls(stmt_select_by_fil_exact);
stmt_select_by_fil_near = Db_stmt_.Rls(stmt_select_by_fil_near);
}
public void Create_tbl() {
conn.Ddl_create_tbl(Db_meta_tbl.new_(tbl_name, flds
, Db_meta_idx.new_unique_by_tbl(tbl_name, "owner", fld_owner_id, fld_id, fld_w, fld_time, fld_page)
));
}
public void Insert(int id, int thm_owner_id, int width, int height, double thumbtime, int page, int bin_db_id, long size) {
if (stmt_insert == null) stmt_insert = conn.Stmt_insert(tbl_name, flds);
stmt_insert.Clear()
.Val_int(fld_id, id)
.Val_int(fld_owner_id, thm_owner_id)
.Val_int(fld_w, width)
.Val_int(fld_h, height);
if (schema_thm_page) {
stmt_insert.Val_double (fld_time, Xof_lnki_time.Db_save_double(thumbtime));
stmt_insert.Val_int (fld_page, Xof_lnki_page.Db_save_int(page));
}
else
stmt_insert.Val_int (fld_time, Xof_lnki_time.Db_save_int(thumbtime));
stmt_insert
.Val_int(fld_bin_db_id, bin_db_id)
.Val_long(fld_size, size)
.Val_str(fld_modified, Modified_null_str)
.Val_str(fld_hash, Hash_null)
.Exec_insert();
}
public boolean Select_itm_by_w_exact(int dir_id, int fil_id, Fsd_thm_itm thm) {
if (stmt_select_by_fil_exact == null) stmt_select_by_fil_exact = conn.Stmt_select(tbl_name, flds, String_.Ary_wo_null(fld_owner_id, fld_w, fld_time, fld_page));
stmt_select_by_fil_exact.Clear().Crt_int(fld_owner_id, fil_id).Crt_int(fld_w, thm.W());
if (schema_thm_page) {
stmt_select_by_fil_exact.Crt_double (fld_time, Xof_lnki_time.Db_save_double(thm.Time()));
stmt_select_by_fil_exact.Crt_int (fld_page, Xof_lnki_page.Db_save_int(thm.Page()));
}
else {
stmt_select_by_fil_exact.Crt_int (fld_time, Xof_lnki_time.Db_save_int(thm.Time()));
}
Db_rdr rdr = stmt_select_by_fil_exact.Exec_select__rls_manual();
try {
return rdr.Move_next()
? Ctor_by_load(thm, rdr, dir_id)
: false;
}
finally {rdr.Rls();}
}
public boolean Select_itm_by_w_near(int dir_id, int fil_id, Fsd_thm_itm thm) {
if (stmt_select_by_fil_near == null) stmt_select_by_fil_near = conn.Stmt_select(tbl_name, flds, fld_owner_id);
List_adp list = List_adp_.new_();
Db_rdr rdr = stmt_select_by_fil_near.Clear().Crt_int(fld_owner_id, fil_id).Exec_select__rls_manual();
try {
while (rdr.Move_next()) {
Fsd_thm_itm itm = Fsd_thm_itm.new_();
Ctor_by_load(itm, rdr, dir_id);
list.Add(itm);
}
return Match_nearest(list, thm, schema_thm_page);
}
finally {rdr.Rls();}
}
private boolean Ctor_by_load(Fsd_thm_itm itm, Db_rdr rdr, int dir_id) {
int thm_id = rdr.Read_int(fld_id);
int fil_id = rdr.Read_int(fld_owner_id);
int w = rdr.Read_int(fld_w);
int h = rdr.Read_int(fld_h);
long size = rdr.Read_long(fld_size);
String modified = rdr.Read_str(fld_modified);
String hash = rdr.Read_str(fld_hash);
int bin_db_id = rdr.Read_int(fld_bin_db_id);
double time = 0;
int page = 0;
if (schema_thm_page) {
time = Xof_lnki_time.Db_load_double(rdr, fld_time);
page = Xof_lnki_page.Db_load_int(rdr, fld_page);
}
else {
time = Xof_lnki_time.Db_load_int(rdr, fld_time);
page = Xof_lnki_page.Null;
}
itm.Ctor(mnt_id, dir_id, fil_id, thm_id, bin_db_id, w, h, time, page, size, modified, hash);
return true;
}
public static final DateAdp Modified_null = null;
public static final String Hash_null = "", Modified_null_str = "";
public static boolean Match_nearest(List_adp list, Fsd_thm_itm thm, boolean schema_thm_page) {
int len = list.Count(); if (len == 0) return Bool_.N;
list.Sort_by(Fsdb_thm_itm_sorter.I);
int thm_w = thm.W(), thm_page = thm.Page(); double thm_time = thm.Time();
Fsd_thm_itm max = null;
for (int i = 0; i < len; ++i) {
Fsd_thm_itm comp = (Fsd_thm_itm)list.Get_at(i);
int comp_w = comp.W();
int comp_page = schema_thm_page ? comp.Page() : thm_page;
if ( thm_w == comp_w
&& thm_time == comp.Time()
&& thm_page == comp_page
) { // exact match
thm.Init_by_match(comp);
return Bool_.Y;
}
if (comp_w > thm_w) max = comp;
else if (max == null) max = comp;
else break;
}
if (max == null) return Bool_.N;
thm.Init_by_match(max);
return Bool_.Y;
}
}

View File

@@ -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.fsdb.data; import gplx.*; import gplx.fsdb.*;
import org.junit.*;
public class Fsd_thm_tbl_tst {
@Before public void init() {fxt.Clear();} private Fsd_thm_tbl_fxt fxt = new Fsd_thm_tbl_fxt();
@Test public void Basic() {
fxt.Init_list(fxt.Make(100), fxt.Make(200), fxt.Make(400));
fxt.Test_match_nearest_itm(fxt.Make(400), fxt.Make(400));
fxt.Test_match_nearest_itm(fxt.Make(200), fxt.Make(200));
fxt.Test_match_nearest_itm(fxt.Make(100), fxt.Make(100));
fxt.Test_match_nearest_itm(fxt.Make(350), fxt.Make(400));
fxt.Test_match_nearest_itm(fxt.Make(150), fxt.Make(200));
fxt.Test_match_nearest_itm(fxt.Make(999), fxt.Make(400));
}
@Test public void Empty() {
fxt.Init_list(); // no items
fxt.Test_match_nearest_itm(fxt.Make(100), Fsd_thm_itm.Null);
}
}
class Fsd_thm_tbl_fxt {
private final List_adp list = List_adp_.new_();
public void Clear() {list.Clear();}
public Fsd_thm_itm Make(int w) {
double time = gplx.xowa.files.Xof_lnki_time.Null;
int page = gplx.xowa.files.Xof_lnki_page.Null;
Fsd_thm_itm rv = Fsd_thm_itm.new_();
rv.Init_by_req(w, time, page);
return rv;
}
public void Init_list(Fsd_thm_itm... ary) {list.Add_many((Object[])ary);}
public void Test_match_nearest_itm(Fsd_thm_itm req, Fsd_thm_itm expd) {
Fsd_thm_tbl.Match_nearest(list, req, Bool_.Y);
if (expd == Fsd_thm_itm.Null) {
Tfds.Eq(req.Req_w(), 0);
}
else {
Tfds.Eq(expd.W(), req.W());
Tfds.Eq(expd.Time(), req.Time());
Tfds.Eq(expd.Page(), req.Page());
}
}
}

View File

@@ -0,0 +1,111 @@
/*
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.fsdb.meta; import gplx.*; import gplx.fsdb.*;
import gplx.core.primitives.*; import gplx.cache.*; import gplx.ios.*;
import gplx.dbs.*; import gplx.dbs.engines.sqlite.*; import gplx.fsdb.data.*;
public class Fsm_atr_fil {
private final Fsm_mnt_itm mnt_itm; private final int mnt_id;
private Fsd_dir_tbl tbl_dir; private Fsd_fil_tbl tbl_fil; private Fsd_thm_tbl tbl_thm;
private final Gfo_cache_mgr_bry dir_cache = new Gfo_cache_mgr_bry(); private Gfo_cache_mgr_bry fil_cache; private Bry_bfr fil_cache_key_bfr;
public Fsm_atr_fil(Fsm_mnt_itm mnt_itm, int id, String url_rel, Db_conn conn, boolean schema_is_1, boolean schema_thm_page) {
this.mnt_itm = mnt_itm; this.mnt_id = mnt_itm.Id();
this.id = id; this.url_rel = url_rel; this.conn = conn;
this.tbl_dir = new Fsd_dir_tbl(conn, schema_is_1);
this.tbl_fil = new Fsd_fil_tbl(conn, schema_is_1, mnt_id);
this.tbl_thm = new Fsd_thm_tbl(conn, schema_is_1, mnt_id, schema_thm_page);
}
public int Id() {return id;} private final int id;
public String Url_rel() {return url_rel;} private final String url_rel;
public Db_conn Conn() {return conn;} private final Db_conn conn;
public Fsd_fil_itm Select_fil_or_null(byte[] dir, byte[] fil) {
int dir_id = Get_dir_id_or_neg1(dir);
return dir_id == Int_.Neg1 ? Fsd_fil_itm.Null : tbl_fil.Select_or_null(dir_id, fil);
}
public boolean Select_thm(boolean exact, Fsd_thm_itm rv, int dir_id, int fil_id) {
return exact ? tbl_thm.Select_itm_by_w_exact(dir_id, fil_id, rv) : tbl_thm.Select_itm_by_w_near(dir_id, fil_id, rv);
}
public int Insert_fil(Fsd_fil_itm rv, byte[] dir, byte[] fil, int ext_id, int bin_db_id, long bin_len, Io_stream_rdr bin_rdr) {
int dir_id = Get_dir_id_or_make(dir);
int fil_id = Get_fil_id_or_make(Tid_none, dir_id, fil, ext_id, bin_db_id, bin_len);
rv.Ctor(mnt_id, fil_id, dir_id, bin_db_id, fil, ext_id);
return fil_id;
}
public int Insert_img(Fsd_img_itm rv, byte[] dir, byte[] fil, int ext_id, int img_w, int img_h, int bin_db_id, long bin_len, Io_stream_rdr bin_rdr) {
int dir_id = Get_dir_id_or_make(dir);
int fil_id = Get_fil_id_or_make(Tid_img, dir_id, fil, ext_id, bin_db_id, bin_len);
rv.Ctor(mnt_id, dir_id, fil_id, bin_db_id);
return fil_id;
}
public int Insert_thm(Fsd_thm_itm rv, byte[] dir, byte[] fil, int ext_id, int w, int h, double time, int page, int bin_db_id, long bin_len, Io_stream_rdr bin_rdr) {
int dir_id = Get_dir_id_or_make(dir);
int fil_id = Get_fil_id_or_make(Tid_thm, dir_id, fil, ext_id, Fsd_bin_tbl.Bin_db_id_null, Fsd_bin_tbl.Size_null); // NOTE: bin_db_id must be set to NULL
int thm_id = mnt_itm.Next_id();
tbl_thm.Insert(thm_id, fil_id, w, h, time, page, bin_db_id, bin_len);
rv.Ctor(mnt_id, dir_id, fil_id, thm_id, bin_db_id, w, h, time, page, bin_len, Fsd_thm_tbl.Modified_null_str, Fsd_thm_tbl.Hash_null);
return thm_id;
}
public void Fil_cache_enabled_y_() {
fil_cache = new Gfo_cache_mgr_bry();
fil_cache_key_bfr = Bry_bfr.reset_(255);
tbl_fil.Select_all(fil_cache_key_bfr, fil_cache);
}
private int Get_dir_id_or_neg1(byte[] dir_bry) {
Object rv_obj = dir_cache.Get_or_null(dir_bry);
if (rv_obj == null) { // not in mem
Fsd_dir_itm itm = tbl_dir.Select_or_null(dir_bry); // try db
if (itm == Fsd_dir_itm.Null) return -1; // not in db
int dir_id = itm.Dir_id();
dir_cache.Add(dir_bry, Int_obj_ref.new_(dir_id)); // add to mem
return dir_id;
}
else
return ((Int_obj_ref)rv_obj).Val();
}
private int Get_dir_id_or_make(byte[] dir_bry) {
int rv = Get_dir_id_or_neg1(dir_bry);
if (rv == -1) {
rv = mnt_itm.Next_id();
tbl_dir.Insert(rv, dir_bry, Fsd_dir_itm.Owner_root);
dir_cache.Add(dir_bry, Int_obj_ref.new_(rv));
}
return rv;
}
private int Get_fil_id_or_make(int xtn_tid, int dir_id, byte[] fil, int ext_id, int bin_db_id, long bin_len) {
if (fil_cache != null) {
byte[] cache_key = Fsd_fil_itm.Gen_cache_key(fil_cache_key_bfr, dir_id, fil);
Object cache_obj = fil_cache.Get_or_null(cache_key);
if (cache_obj != null) return ((Fsd_fil_itm)cache_obj).Fil_id();
}
Fsd_fil_itm fil_itm = tbl_fil.Select_or_null(dir_id, fil);
int fil_id = -1;
if (fil_itm == Fsd_fil_itm.Null) { // new item
fil_id = mnt_itm.Next_id();
tbl_fil.Insert(fil_id, dir_id, fil, xtn_tid, ext_id, bin_len, bin_db_id);
}
else { // existing item
fil_id = fil_itm.Fil_id();
if ( fil_itm.Bin_db_id() == Fsd_bin_tbl.Bin_db_id_null // prv row was previously inserted by thumb
&& xtn_tid != Tid_thm // cur row is not thumb
) {
tbl_fil.Update(fil_id, dir_id, fil, xtn_tid, ext_id, bin_len, bin_db_id); // update props; note that thumb inserts null props, whereas file will insert real props (EX: bin_db_id)
}
}
return fil_id;
}
private static final int Tid_none = 0, Tid_thm = 1, Tid_img = 2;
}

View File

@@ -0,0 +1,34 @@
/*
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.fsdb.meta; import gplx.*; import gplx.fsdb.*;
import gplx.dbs.*; import gplx.fsdb.data.*;
public class Fsm_atr_mgr {
private Fsdb_db_mgr core_mgr; private Fsm_atr_tbl tbl; private Fsm_atr_fil db__core; private Fsm_mnt_itm mnt_itm;
public Fsm_atr_mgr(Fsdb_db_mgr core_mgr, Db_conn conn, Fsm_mnt_itm mnt_itm) {
this.core_mgr = core_mgr; this.mnt_itm = mnt_itm;
this.tbl = new Fsm_atr_tbl(conn, core_mgr.File__schema_is_1());
}
public void Ctor_by_load(boolean schema_thm_page) {
this.db__core = tbl.Select_1st_or_fail(mnt_itm, core_mgr, mnt_itm.Id(), schema_thm_page);
}
public Fsm_atr_fil Db__core() {return db__core;}
public Fsd_fil_itm Select_fil_or_null(byte[] dir, byte[] fil) {return db__core.Select_fil_or_null(dir, fil);}
public boolean Select_thm(boolean exact, Fsd_thm_itm rv, int dir_id, int fil_id) {return db__core.Select_thm(exact, rv, dir_id, fil_id);}
public void Txn_bgn() {db__core.Conn().Txn_bgn();}
public void Txn_end() {db__core.Conn().Txn_end();}
}

View File

@@ -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.fsdb.meta; import gplx.*; import gplx.fsdb.*;
import gplx.dbs.*; import gplx.dbs.qrys.*;
public class Fsm_atr_tbl {
private final String tbl_name; private final Db_meta_fld_list flds = Db_meta_fld_list.new_();
private final String fld_uid, fld_url;
private final Db_conn conn;
public Fsm_atr_tbl(Db_conn conn, boolean schema_is_1) {
this.conn = conn;
String fld_prefix = "";
if (schema_is_1) {tbl_name = "fsdb_db_atr";}
else {tbl_name = "fsdb_dba"; fld_prefix = "dba_";}
this.fld_uid = flds.Add_int_pkey (fld_prefix + "uid");
this.fld_url = flds.Add_str (fld_prefix + "url", 255);
}
public void Create_tbl() {conn.Ddl_create_tbl(Db_meta_tbl.new_(tbl_name, flds));}
public Fsm_atr_fil Select_1st_or_fail(Fsm_mnt_itm mnt_itm, Fsdb_db_mgr core_mgr, int mnt_id, boolean schema_thm_page) {
Db_rdr rdr = conn.Stmt_select(tbl_name, flds, Db_meta_fld.Ary_empty).Exec_select__rls_auto();
boolean schema_is_1 = core_mgr.File__schema_is_1();
try {
if (rdr.Move_next()) {
String url_rel = rdr.Read_str(fld_url);
return new Fsm_atr_fil
( mnt_itm
, rdr.Read_int(fld_uid)
, url_rel
, core_mgr.File__atr_file__at(mnt_id).Conn()
, schema_is_1
, schema_thm_page
);
}
}
finally {rdr.Rls();}
throw Exc_.new_("missing atr db", "conn", conn.Conn_info().Xto_api());
}
public void Insert(int id, String url_rel) {
conn.Stmt_insert(tbl_name, flds).Val_int(fld_uid, id).Val_str(fld_url, url_rel).Exec_insert();
}
}

View File

@@ -0,0 +1,40 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.fsdb.meta; import gplx.*; import gplx.fsdb.*;
import gplx.ios.*; import gplx.dbs.*;
import gplx.fsdb.data.*;
public class Fsm_bin_fil {
private final Fsd_bin_tbl tbl;
public Fsm_bin_fil(boolean schema_is_1, int id, Io_url url, String url_rel, Db_conn conn, long bin_len) {
this.id = id; this.url = url; this.url_rel = url_rel; this.conn = conn; this.bin_len = bin_len;
this.tbl = new Fsd_bin_tbl(conn, schema_is_1);
}
public int Id() {return id;} private final int id;
public Io_url Url() {return url;} private Io_url url;
public String Url_rel() {return url_rel;} private final String url_rel;
public long Bin_len() {return bin_len;} public void Bin_len_(long v) {bin_len = v;} private long bin_len;
public Db_conn Conn() {return conn;} private final Db_conn conn;
public boolean Select_to_url(int id, Io_url url) {return tbl.Select_to_url(id, url);}
public Io_stream_rdr Select_as_rdr(int id) {return tbl.Select_as_rdr(id);}
public void Insert(int bin_id, byte owner_tid, long rdr_len, gplx.ios.Io_stream_rdr rdr) {
tbl.Insert_rdr(bin_id, owner_tid, rdr_len, rdr);
Bin_len_(bin_len + rdr_len);
}
public static final Fsm_bin_fil[] Ary_empty = new Fsm_bin_fil[0];
public static final long Bin_len_null = 0;
}

View File

@@ -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.fsdb.meta; import gplx.*; import gplx.fsdb.*;
import gplx.ios.*; import gplx.dbs.*;
public class Fsm_bin_mgr {
private final Fsdb_db_mgr core_mgr; private final int mnt_id; private final Fsm_bin_tbl tbl;
private Fsm_bin_fil[] dbs__ary = Fsm_bin_fil.Ary_empty; private int dbs__ary_len = 0; private Fsm_bin_fil nth_db;
public Fsm_bin_mgr(Fsdb_db_mgr core_mgr, Db_conn conn, int mnt_id) {
this.core_mgr = core_mgr; this.mnt_id = mnt_id;
this.tbl = new Fsm_bin_tbl(conn, core_mgr.File__schema_is_1(), mnt_id);
}
public void Ctor_by_load() {
this.dbs__ary = tbl.Select_all(core_mgr);
this.dbs__ary_len = dbs__ary.length;
if (dbs__ary_len > 0) this.nth_db = dbs__ary[dbs__ary_len - 1];
}
public int Dbs__len() {return dbs__ary_len;}
public Fsm_bin_fil Dbs__get_nth() {return nth_db;}
public Fsm_bin_fil Dbs__get_at(int i) {return dbs__ary[i];}
public Fsm_bin_fil Dbs__make(String file_name) {
Fsdb_db_file db = core_mgr.File__bin_file__new(mnt_id, file_name);
Fsm_bin_fil rv = new Fsm_bin_fil(core_mgr.File__schema_is_1(), dbs__ary_len, db.Url(), db.Url().NameAndExt(), db.Conn(), Fsm_bin_fil.Bin_len_null);
tbl.Insert(rv.Id(), rv.Url_rel());
Dbs__add(rv);
return rv;
}
public void Insert(int db_id, int bin_id, byte owner_tid, long bin_len, Io_stream_rdr bin_rdr) {
Fsm_bin_fil fil = dbs__ary[db_id];
fil.Insert(bin_id, owner_tid, bin_len, bin_rdr);
dbs__ary[db_id].Insert(bin_id, owner_tid, bin_len, bin_rdr);
}
public void Txn_bgn() {
for (int i = 0; i < dbs__ary_len; ++i)
dbs__ary[i].Conn().Txn_bgn();
}
public void Txn_end() {
for (int i = 0; i < dbs__ary_len; ++i)
dbs__ary[i].Conn().Txn_end();
}
private void Dbs__add(Fsm_bin_fil fil) {
this.dbs__ary = (Fsm_bin_fil[])Array_.Resize(dbs__ary, dbs__ary_len + 1);
this.dbs__ary[dbs__ary_len++] = fil;
this.nth_db = fil;
}
}

View File

@@ -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.fsdb.meta; import gplx.*; import gplx.fsdb.*;
import gplx.dbs.*; import gplx.dbs.qrys.*;
public class Fsm_bin_tbl {
private final String tbl_name; private final Db_meta_fld_list flds = Db_meta_fld_list.new_();
private final String fld_uid, fld_url, fld_bin_len, fld_bin_max;
private final Db_conn conn; private int mnt_id;
public Fsm_bin_tbl(Db_conn conn, boolean schema_is_1, int mnt_id) {
this.conn = conn; this.mnt_id = mnt_id;
String fld_prefix = "";
if (schema_is_1) {tbl_name = "fsdb_db_bin";}
else {tbl_name = "fsdb_dbb"; fld_prefix = "dbb_";}
fld_uid = flds.Add_int_pkey (fld_prefix + "uid");
fld_url = flds.Add_str (fld_prefix + "url", 255);
if (schema_is_1) {
fld_bin_len = flds.Add_long("bin_len");
fld_bin_max = flds.Add_long("bin_max");
}
else {
fld_bin_len = Db_meta_fld.Key_null;
fld_bin_max = Db_meta_fld.Key_null;
}
}
public void Create_tbl() {conn.Ddl_create_tbl(Db_meta_tbl.new_(tbl_name, flds));}
public void Insert(int id, String url_rel) {
conn.Stmt_insert(tbl_name, flds).Crt_int(fld_uid, id).Val_str(fld_url, url_rel).Val_long(fld_bin_len, 0).Val_long(fld_bin_max, 0).Exec_insert();
}
public Fsm_bin_fil[] Select_all(Fsdb_db_mgr db_conn_mgr) {
List_adp rv = List_adp_.new_();
Db_rdr rdr = conn.Stmt_select_order(tbl_name, flds, Db_meta_fld.Ary_empty, fld_uid).Clear().Exec_select__rls_auto();
try {
while (rdr.Move_next()) {
int bin_id = rdr.Read_int(fld_uid);
String bin_url = rdr.Read_str(fld_url);
Fsdb_db_file bin_db = db_conn_mgr.File__bin_file__at(mnt_id, bin_id, bin_url);
Fsm_bin_fil itm = new Fsm_bin_fil(db_conn_mgr.File__schema_is_1(), bin_id, bin_db.Url(), bin_url, bin_db.Conn(), Fsm_bin_fil.Bin_len_null);
rv.Add(itm);
}
} finally {rdr.Rls();}
return (Fsm_bin_fil[])rv.To_ary(Fsm_bin_fil.class);
}
}

View File

@@ -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.fsdb.meta; import gplx.*; import gplx.fsdb.*;
import gplx.dbs.*; import gplx.dbs.cfgs.*; import gplx.fsdb.meta.*;
public class Fsm_cfg_mgr {
private final Db_cfg_tbl tbl; private final Hash_adp grp_hash = Hash_adp_.new_();
public Fsm_cfg_mgr(Fsdb_db_mgr db_conn_mgr, Db_conn conn) {
this.tbl = new Db_cfg_tbl(conn, db_conn_mgr.File__cfg_tbl_name());
}
public void Ctor_by_load() {
Db_cfg_hash hash = Grps_get_or_load(Grp_core);
this.next_id = hash.Get(Key_next_id).To_int_or(-1); if (next_id == -1) throw Exc_.new_("next_id not found in cfg", "url", tbl.Conn().Conn_info().Xto_api());
this.schema_thm_page = hash.Get(Key_schema_thm_page).To_yn_or_n();
this.patch__next_id = hash.Get(Key_patch__next_id).To_yn_or_n();
this.patch__page_gt_1 = hash.Get(Key_patch__page_gt_1).To_yn_or_n();
}
public Db_cfg_tbl Tbl() {return tbl;}
public int Next_id() {return next_id++;} private int next_id = 1;
public void Next_id_commit() {tbl.Update_int("core", "next_id", next_id);}
public boolean Schema_thm_page() {return schema_thm_page;} private boolean schema_thm_page = true;
public boolean Patch_next_id() {return patch__next_id;} private boolean patch__next_id = true;
public void Patch_next_id_exec(int last_id) {
if (last_id >= next_id)
next_id = last_id + 1;
tbl.Insert_yn(Grp_core, Key_patch__next_id, Bool_.Y);
}
public boolean Patch__page_gt_1() {return patch__page_gt_1;} private boolean patch__page_gt_1 = false;
public void Patch__save(String cfg_key) {tbl.Insert_yn(Fsm_cfg_mgr.Grp_core, cfg_key, Bool_.Y);}
public Db_cfg_hash Grps_get_or_load(String grp_key) {
Db_cfg_hash rv = (Db_cfg_hash)grp_hash.Get_by(grp_key);
if (rv == null) {
rv = tbl.Select_as_hash(grp_key);
grp_hash.Add(grp_key, rv);
}
return rv;
}
public static final String Grp_core = "core";
public static final String Key_next_id = "next_id", Key_schema_thm_page = "schema.thm.page", Key_patch__next_id = "patch.next_id", Key_patch__page_gt_1 = "patch.page_gt_1";
}

View File

@@ -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.fsdb.meta; import gplx.*; import gplx.fsdb.*;
public class Fsm_id_itm {
public Fsm_id_itm(String key, int id, int version) {this.key = key; this.id = id; this.version = version;}
public String Key() {return key;} private final String key;
public int Id() {return id;} private final int id;
public int Version() {return version;} private final int version;
}

View File

@@ -0,0 +1,73 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.fsdb.meta; import gplx.*; import gplx.fsdb.*;
import gplx.ios.*; import gplx.dbs.*; import gplx.fsdb.data.*;
public class Fsm_mnt_itm {
public Fsm_mnt_itm(int id, String name, String url_rel) {this.id = id; this.name = name; this.url_rel = url_rel;}
public int Id() {return id;} private final int id;
public String Name() {return name;} private final String name;
public String Url_rel() {return url_rel;} private final String url_rel;
public Fsm_atr_mgr Atr_mgr() {return atr_mgr;} private Fsm_atr_mgr atr_mgr;
public Fsm_bin_mgr Bin_mgr() {return bin_mgr;} private Fsm_bin_mgr bin_mgr;
public Fsm_cfg_mgr Cfg_mgr() {return cfg_mgr;} private Fsm_cfg_mgr cfg_mgr;
public Fsdb_db_mgr Db_mgr() {return db_mgr;} private Fsdb_db_mgr db_mgr;
public void Ctor_by_load(Fsdb_db_mgr db_mgr) {
this.db_mgr = db_mgr;
Db_conn conn = db_mgr.File__abc_file__at(id).Conn();
cfg_mgr = new Fsm_cfg_mgr(db_mgr, conn);
atr_mgr = new Fsm_atr_mgr(db_mgr, conn, this);
bin_mgr = new Fsm_bin_mgr(db_mgr, conn, id);
cfg_mgr.Ctor_by_load();
atr_mgr.Ctor_by_load(cfg_mgr.Schema_thm_page());
bin_mgr.Ctor_by_load();
if (!cfg_mgr.Patch_next_id()) Fsm_mnt_itm_.Patch_next_id(this, name);
}
public int Next_id() {return cfg_mgr.Next_id();}
public Fsd_fil_itm Select_fil_or_null(byte[] dir, byte[] fil) {return atr_mgr.Select_fil_or_null(dir, fil);}
public boolean Select_thm(boolean exact, Fsd_thm_itm rv, byte[] dir, byte[] fil) {
Fsd_fil_itm fil_itm = atr_mgr.Select_fil_or_null(dir, fil);
return fil_itm == Fsd_fil_itm.Null ? Bool_.N : atr_mgr.Select_thm(exact, rv, fil_itm.Dir_id(), fil_itm.Fil_id());
}
public void Insert_img(Fsd_img_itm rv, Fsm_atr_fil atr_fil, Fsm_bin_fil bin_fil, byte[] dir, byte[] fil, int ext_id, int img_w, int img_h, long bin_len, Io_stream_rdr bin_rdr) {
int fil_id = atr_fil.Insert_img(rv, dir, fil, ext_id, img_w, img_h, bin_fil.Id(), bin_len, bin_rdr);
bin_fil.Insert(fil_id, Fsd_bin_tbl.Owner_tid_fil, bin_len, bin_rdr);
}
public void Insert_fil(Fsd_fil_itm rv, Fsm_atr_fil atr_fil, Fsm_bin_fil bin_fil, byte[] dir, byte[] fil, int ext_id, long bin_len, gplx.ios.Io_stream_rdr bin_rdr) {
int fil_id = atr_fil.Insert_fil(rv, dir, fil, ext_id, bin_fil.Id(), bin_len, bin_rdr);
bin_fil.Insert(fil_id, Fsd_bin_tbl.Owner_tid_fil, bin_len, bin_rdr);
}
public void Insert_thm(Fsd_thm_itm rv, Fsm_atr_fil atr_fil, Fsm_bin_fil bin_fil, byte[] dir, byte[] fil, int ext_id, int w, int h, double time, int page, long bin_len, Io_stream_rdr bin_rdr) {
int thm_id = atr_fil.Insert_thm(rv, dir, fil, ext_id, w, h, time, page, bin_fil.Id(), bin_len, bin_rdr);
bin_fil.Insert(thm_id, Fsd_bin_tbl.Owner_tid_thm, bin_len, bin_rdr);
}
public void Txn_bgn() {atr_mgr.Txn_bgn(); bin_mgr.Txn_bgn();}
public void Txn_end() {atr_mgr.Txn_end(); bin_mgr.Txn_end();}
}
class Fsm_mnt_itm_ {
public static void Patch_next_id(Fsm_mnt_itm abc_mgr, String name) {
if (!String_.Eq(name, "fsdb.user")) return;
Fsm_atr_mgr atr_mgr = abc_mgr.Atr_mgr();
Fsm_cfg_mgr cfg_mgr = abc_mgr.Cfg_mgr();
int last_id = -1;
Fsm_atr_fil atr_fil = atr_mgr.Db__core();
int max_fil_id = Db_conn_.Select_fld0_as_int_or(atr_fil.Conn(), "SELECT Max(fil_id) AS MaxId FROM fsdb_fil;", -1);
int max_thm_id = Db_conn_.Select_fld0_as_int_or(atr_fil.Conn(), "SELECT Max(thm_id) AS MaxId FROM fsdb_xtn_thm;", -1);
last_id = max_fil_id > max_thm_id ? max_fil_id : max_thm_id;
cfg_mgr.Patch_next_id_exec(last_id);
}
}

View File

@@ -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.fsdb.meta; import gplx.*; import gplx.fsdb.*;
import gplx.dbs.*; import gplx.dbs.cfgs.*; import gplx.xowa.files.*; import gplx.xowa.files.fsdb.*;
public class Fsm_mnt_mgr implements GfoInvkAble {
private Db_cfg_tbl cfg_tbl; private Fsm_mnt_tbl mnt_tbl;
private Fsm_mnt_itm[] mnt_ary; private int mnt_ary_len = 0;
public void Ctor_by_load(Fsdb_db_mgr db_core) {
Db_conn conn = db_core.File__mnt_file().Conn();
this.cfg_tbl = new Db_cfg_tbl (conn, db_core.File__cfg_tbl_name());
this.mnt_tbl = new Fsm_mnt_tbl (conn, db_core.File__schema_is_1());
this.mnt_ary = mnt_tbl.Select_all();
this.mnt_ary_len = mnt_ary.length;
for (int i = 0; i < mnt_ary_len; ++i) {
mnt_ary[i].Ctor_by_load(db_core);
}
this.insert_idx = cfg_tbl.Select_int(Cfg_grp_core, Cfg_key_mnt_insert_idx);
Db_cfg_hash cfg_hash = this.Mnts__get_main().Cfg_mgr().Grps_get_or_load(Xof_fsdb_mgr_cfg.Grp_xowa);
boolean use_thumb_w = cfg_hash.Get(Xof_fsdb_mgr_cfg.Key_upright_use_thumb_w).To_yn_or_n();
boolean fix_default = cfg_hash.Get(Xof_fsdb_mgr_cfg.Key_upright_fix_default).To_yn_or_n();
this.patch_upright_tid = Xof_patch_upright_tid_.Merge(use_thumb_w, fix_default);
}
public int Mnts__len() {return mnt_ary_len;}
public Fsm_mnt_itm Mnts__get_at(int i) {return mnt_ary[i];}
public Fsm_mnt_itm Mnts__get_main() {return mnt_ary[Mnt_idx_main];}
public Fsm_mnt_itm Mnts__get_insert() {return mnt_ary[insert_idx];} public void Mnts__get_insert_idx_(int v) {insert_idx = v;} private int insert_idx = Mnt_idx_user;
public Fsm_bin_fil Bins__at(int mnt_id, int bin_db_id) {return mnt_ary[mnt_id].Bin_mgr().Dbs__get_at(bin_db_id);}
public int Patch_upright() {return patch_upright_tid;} private int patch_upright_tid = Xof_patch_upright_tid_.Tid_all;
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {return GfoInvkAble_.Rv_unhandled;}
public static final int Mnt_idx_main = 0, Mnt_idx_user = 1, Insert_to_bin_null = -1;
public static void Patch(Db_cfg_tbl cfg_tbl) {
cfg_tbl.Upsert_str(Xof_fsdb_mgr_cfg.Grp_xowa, Xof_fsdb_mgr_cfg.Key_gallery_fix_defaults , "y");
cfg_tbl.Upsert_str(Xof_fsdb_mgr_cfg.Grp_xowa, Xof_fsdb_mgr_cfg.Key_gallery_packed , "y");
cfg_tbl.Upsert_str(Xof_fsdb_mgr_cfg.Grp_xowa, Xof_fsdb_mgr_cfg.Key_upright_use_thumb_w , "y");
cfg_tbl.Upsert_str(Xof_fsdb_mgr_cfg.Grp_xowa, Xof_fsdb_mgr_cfg.Key_upright_fix_default , "y");
}
public static void Patch_core(Db_cfg_tbl cfg_tbl) { // NOTE: thes need to be upserts else upgrading will fail; DATE:2015-05-23
cfg_tbl.Upsert_int (Fsm_cfg_mgr.Grp_core, Fsm_cfg_mgr.Key_next_id , 1); // start next_id at 1
cfg_tbl.Upsert_yn (Fsm_cfg_mgr.Grp_core, Fsm_cfg_mgr.Key_schema_thm_page , Bool_.Y); // new dbs automatically have page and time in fsdb_xtn_tm
cfg_tbl.Upsert_yn (Fsm_cfg_mgr.Grp_core, Fsm_cfg_mgr.Key_patch__next_id , Bool_.Y); // new dbs automatically have correct next_id
}
public static final String Cfg_grp_core = "core", Cfg_key_mnt_insert_idx = "mnt.insert_idx"; // SERIALIZED
}

View File

@@ -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.fsdb.meta; import gplx.*; import gplx.fsdb.*;
import gplx.dbs.*;
public class Fsm_mnt_tbl implements RlsAble {
private final String tbl_name = "fsdb_mnt"; private final Db_meta_fld_list flds = Db_meta_fld_list.new_();
private final String fld_id, fld_name, fld_url;
private final Db_conn conn;
public Fsm_mnt_tbl(Db_conn conn, boolean schema_is_1) {
this.conn = conn;
fld_id = flds.Add_int_pkey ("mnt_id");
fld_name = flds.Add_str ("mnt_name", 255);
fld_url = flds.Add_str ("mnt_url", 255);
conn.Rls_reg(this);
}
public void Create_tbl() {
Db_meta_tbl meta = Db_meta_tbl.new_(tbl_name, flds);
conn.Ddl_create_tbl(meta);
this.Insert(Fsm_mnt_mgr.Mnt_idx_main, Mnt_name_main, Mnt_name_main);
this.Insert(Fsm_mnt_mgr.Mnt_idx_user, Mnt_name_user, Mnt_name_user);
}
public void Rls() {}
public void Insert(int id, String name, String url) {
Db_stmt stmt = conn.Stmt_insert(tbl_name, flds);
stmt.Clear().Val_int(fld_id, id).Val_str(fld_name, name).Val_str(fld_url, url).Exec_insert();
}
public void Update(int id, String name, String url) {
Db_stmt stmt = conn.Stmt_update_exclude(tbl_name, flds, fld_id);
stmt.Clear().Val_str(fld_name, name).Val_str(fld_url, url).Crt_int(fld_id, id).Exec_update();
}
public Fsm_mnt_itm[] Select_all() {
List_adp list = List_adp_.new_();
Db_rdr rdr = conn.Stmt_select(tbl_name, flds, Db_meta_fld.Ary_empty).Clear().Exec_select__rls_auto();
try {
while (rdr.Move_next()) {
Fsm_mnt_itm itm = new Fsm_mnt_itm(rdr.Read_int(fld_id), rdr.Read_str(fld_name), rdr.Read_str(fld_url));
list.Add(itm);
}
}
finally {rdr.Rls();}
return (Fsm_mnt_itm[])list.To_ary_and_clear(Fsm_mnt_itm.class);
}
public static final String Mnt_name_main = "fsdb.main", Mnt_name_user = "fsdb.user";
}

View File

@@ -0,0 +1,214 @@
/*
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.gfs; import gplx.*;
interface Gfs_lxr {
byte Lxr_tid();
int Process(Gfs_parser_ctx ctx, int bgn, int end);
}
class Gfs_lxr_whitespace implements Gfs_lxr {
public byte Lxr_tid() {return Gfs_lxr_.Tid_whitespace;}
public int Process(Gfs_parser_ctx ctx, int bgn, int end) {
byte[] src = ctx.Src(); int src_len = ctx.Src_len();
int rv = Gfs_lxr_.Rv_eos, cur_pos;
for (cur_pos = end; cur_pos < src_len; cur_pos++) {
byte b = src[cur_pos];
Object o = ctx.Trie().Match_bgn_w_byte(b, src, cur_pos, src_len);
if (o == null) {
rv = Gfs_lxr_.Rv_null;
ctx.Process_null(cur_pos);
break;
}
else {
Gfs_lxr lxr = (Gfs_lxr)o;
if (lxr.Lxr_tid() == Gfs_lxr_.Tid_whitespace) {}
else {
rv = Gfs_lxr_.Rv_lxr;
ctx.Process_lxr(cur_pos, lxr);
break;
}
}
}
return rv;
}
public static final Gfs_lxr_whitespace _ = new Gfs_lxr_whitespace(); Gfs_lxr_whitespace() {}
}
class Gfs_lxr_comment_flat implements Gfs_lxr {
public Gfs_lxr_comment_flat(byte[] bgn_bry, byte[] end_bry) {
this.bgn_bry = bgn_bry; this.bgn_bry_len = bgn_bry.length;
this.end_bry = end_bry; this.end_bry_len = end_bry.length;
} byte[] bgn_bry, end_bry; int bgn_bry_len, end_bry_len;
public byte Lxr_tid() {return Gfs_lxr_.Tid_comment;}
public int Process(Gfs_parser_ctx ctx, int lxr_bgn, int lxr_end) {
byte[] src = ctx.Src(); int src_len = ctx.Src_len();
int end_pos = Bry_finder.Find_fwd(src, end_bry, lxr_end, src_len);
// if (end_pos == Bry_.NotFound) throw Err_.new_fmt_("comment is not closed: {0}", String_.new_u8(end_bry));
return (end_pos == Bry_.NotFound)
? src_len // allow eos to terminate flat comment; needed for "tidy-always-adds-nl-in-textarea" fix; NOTE: DATE:2014-06-21
: end_pos + end_bry_len; // position after end_bry
}
}
class Gfs_lxr_identifier implements Gfs_lxr {
public byte Lxr_tid() {return Gfs_lxr_.Tid_identifier;}
public int Process(Gfs_parser_ctx ctx, int bgn, int end) {
byte[] src = ctx.Src(); int src_len = ctx.Src_len();
int pos, rv = Gfs_lxr_.Rv_eos;
for (pos = end; pos < src_len; pos++) {
byte b = src[pos];
Object o = ctx.Trie().Match_bgn_w_byte(b, src, pos, src_len);
if (o == null) { // invalid char; stop;
rv = Gfs_lxr_.Rv_null;
ctx.Process_null(pos);
break;
}
else {
Gfs_lxr lxr = (Gfs_lxr)o;
if (lxr.Lxr_tid() == Gfs_lxr_.Tid_identifier) {} // still an identifier; continue
else { // new lxr (EX: "." in "abc."); (a) hold word of "abc"; mark "." as new lxr;
ctx.Hold_word(bgn, pos);
rv = Gfs_lxr_.Rv_lxr;
ctx.Process_lxr(pos, lxr);
break;
}
}
}
if (rv == Gfs_lxr_.Rv_eos) ctx.Process_eos(); // eos
return rv;
}
public static final Gfs_lxr_identifier _ = new Gfs_lxr_identifier(); Gfs_lxr_identifier() {}
}
class Gfs_lxr_semic implements Gfs_lxr {
public byte Lxr_tid() {return Gfs_lxr_.Tid_semic;}
public int Process(Gfs_parser_ctx ctx, int bgn, int end) {
switch (ctx.Prv_lxr()) {
case Gfs_lxr_.Tid_identifier: ctx.Make_nde(bgn, end); ctx.Cur_nde_from_stack(); break; // a;
case Gfs_lxr_.Tid_quote:
case Gfs_lxr_.Tid_paren_end: ctx.Cur_nde_from_stack(); break; // a();
case Gfs_lxr_.Tid_semic: break; // a;; ignore;
default: ctx.Err_mgr().Fail_invalid_lxr(ctx, bgn, this.Lxr_tid(), Byte_ascii.Semic); break;
}
return end;
}
public static final Gfs_lxr_semic _ = new Gfs_lxr_semic(); Gfs_lxr_semic() {}
}
class Gfs_lxr_dot implements Gfs_lxr {
public byte Lxr_tid() {return Gfs_lxr_.Tid_dot;}
public int Process(Gfs_parser_ctx ctx, int bgn, int end) {
switch (ctx.Prv_lxr()) {
case Gfs_lxr_.Tid_identifier: ctx.Make_nde(bgn, end); break; // a.
case Gfs_lxr_.Tid_paren_end: break; // a().
default: ctx.Err_mgr().Fail_invalid_lxr(ctx, bgn, this.Lxr_tid(), Byte_ascii.Dot); break;
}
return end;
}
public static final Gfs_lxr_dot _ = new Gfs_lxr_dot(); Gfs_lxr_dot() {}
}
class Gfs_lxr_paren_bgn implements Gfs_lxr {
public byte Lxr_tid() {return Gfs_lxr_.Tid_paren_bgn;}
public int Process(Gfs_parser_ctx ctx, int bgn, int end) {
switch (ctx.Prv_lxr()) {
case Gfs_lxr_.Tid_identifier: ctx.Make_nde(bgn, end); break; // a(;
default: ctx.Err_mgr().Fail_invalid_lxr(ctx, bgn, this.Lxr_tid(), Byte_ascii.Paren_bgn); break;
}
return end;
}
public static final Gfs_lxr_paren_bgn _ = new Gfs_lxr_paren_bgn(); Gfs_lxr_paren_bgn() {}
}
class Gfs_lxr_paren_end implements Gfs_lxr {
public byte Lxr_tid() {return Gfs_lxr_.Tid_paren_end;}
public int Process(Gfs_parser_ctx ctx, int bgn, int end) {
switch (ctx.Prv_lxr()) {
case Gfs_lxr_.Tid_paren_bgn:
case Gfs_lxr_.Tid_quote: break; // "))", "abc)", "'abc')"
case Gfs_lxr_.Tid_identifier: ctx.Make_atr_by_idf(); break; // 123)
default: ctx.Err_mgr().Fail_invalid_lxr(ctx, bgn, this.Lxr_tid(), Byte_ascii.Paren_end); break;
}
return end;
}
public static final Gfs_lxr_paren_end _ = new Gfs_lxr_paren_end(); Gfs_lxr_paren_end() {}
}
class Gfs_lxr_quote implements Gfs_lxr {
public Gfs_lxr_quote(byte[] bgn_bry, byte[] end_bry) {
this.bgn_bry_len = bgn_bry.length;
this.end_bry = end_bry; this.end_bry_len = end_bry.length;
} private byte[] end_bry; private int bgn_bry_len, end_bry_len;
public byte Lxr_tid() {return Gfs_lxr_.Tid_quote;}
public int Process(Gfs_parser_ctx ctx, int lxr_bgn, int lxr_end) {
byte[] src = ctx.Src(); int src_len = ctx.Src_len();
int end_pos = Bry_finder.Find_fwd(src, end_bry, lxr_end, src_len);
if (end_pos == Bry_.NotFound) throw Exc_.new_("quote is not closed", "end", String_.new_u8(end_bry));
Bry_bfr bfr = ctx.Tmp_bfr().Clear();
int prv_pos = lxr_end;
int nxt_pos = end_pos + end_bry_len;
if (Bry_.Match(src, nxt_pos, nxt_pos + end_bry_len, end_bry)) { // end_bry is doubled; EX: end_bry = ' and raw = a''
while (true) {
bfr.Add_mid(src, prv_pos, end_pos); // add everything up to end_bry
bfr.Add(end_bry); // add end_bry
prv_pos = nxt_pos + end_bry_len; // set prv_pos to after doubled end_bry
end_pos = Bry_finder.Find_fwd(src, end_bry, prv_pos, src_len);
if (end_pos == Bry_.NotFound) throw Exc_.new_("quote is not closed", "end", String_.new_u8(end_bry));
nxt_pos = end_pos + end_bry_len;
if (!Bry_.Match(src, nxt_pos, nxt_pos + end_bry_len, end_bry)) {
bfr.Add_mid(src, prv_pos, end_pos);
break;
}
}
ctx.Make_atr_by_bry(lxr_bgn + bgn_bry_len, end_pos, bfr.Xto_bry_and_clear());
}
else
ctx.Make_atr(lxr_bgn + bgn_bry_len, end_pos);
return end_pos + end_bry_len; // position after quote
}
}
class Gfs_lxr_curly_bgn implements Gfs_lxr {
public byte Lxr_tid() {return Gfs_lxr_.Tid_curly_bgn;}
public int Process(Gfs_parser_ctx ctx, int bgn, int end) {
switch (ctx.Prv_lxr()) {
case Gfs_lxr_.Tid_identifier: ctx.Make_nde(bgn, end); ctx.Stack_add(); break; // a{;
case Gfs_lxr_.Tid_paren_end: ctx.Stack_add(); break; // a(){; NOTE: node exists but needs to be pushed onto stack
default: ctx.Err_mgr().Fail_invalid_lxr(ctx, bgn, this.Lxr_tid(), Byte_ascii.Curly_bgn); break;
}
return end;
}
public static final Gfs_lxr_curly_bgn _ = new Gfs_lxr_curly_bgn(); Gfs_lxr_curly_bgn() {}
}
class Gfs_lxr_curly_end implements Gfs_lxr {
public byte Lxr_tid() {return Gfs_lxr_.Tid_curly_end;}
public int Process(Gfs_parser_ctx ctx, int bgn, int end) {
ctx.Stack_pop(bgn);
return end;
}
public static final Gfs_lxr_curly_end _ = new Gfs_lxr_curly_end(); Gfs_lxr_curly_end() {}
}
class Gfs_lxr_equal implements Gfs_lxr {
public byte Lxr_tid() {return Gfs_lxr_.Tid_eq;}
public int Process(Gfs_parser_ctx ctx, int bgn, int end) {
ctx.Make_nde(bgn, end).Op_tid_(Gfs_nde.Op_tid_assign);
return end;
}
public static final Gfs_lxr_equal _ = new Gfs_lxr_equal(); Gfs_lxr_equal() {}
}
class Gfs_lxr_comma implements Gfs_lxr {
public byte Lxr_tid() {return Gfs_lxr_.Tid_comma;}
public int Process(Gfs_parser_ctx ctx, int bgn, int end) {
switch (ctx.Prv_lxr()) {
case Gfs_lxr_.Tid_identifier: ctx.Make_atr_by_idf(); break; // 123,
}
return end;
}
public static final Gfs_lxr_comma _ = new Gfs_lxr_comma(); Gfs_lxr_comma() {}
}

View File

@@ -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.gfs; import gplx.*;
class Gfs_lxr_ {
public static final int Rv_init = -1, Rv_null = -2, Rv_eos = -3, Rv_lxr = -4;
public static final byte Tid_identifier = 1, Tid_dot = 2, Tid_semic = 3, Tid_paren_bgn = 4, Tid_paren_end = 5, Tid_curly_bgn = 6, Tid_curly_end = 7, Tid_quote = 8, Tid_comma = 9, Tid_whitespace = 10, Tid_comment = 11, Tid_eq = 12;
public static String Tid__name(byte tid) {
switch (tid) {
case Tid_identifier: return "identifier";
case Tid_dot: return "dot";
case Tid_semic: return "semic";
case Tid_paren_bgn: return "paren_bgn";
case Tid_paren_end: return "paren_end";
case Tid_curly_bgn: return "curly_bgn";
case Tid_curly_end: return "curly_end";
case Tid_quote: return "quote";
case Tid_comma: return "comma";
case Tid_whitespace: return "whitespace";
case Tid_comment: return "comment";
case Tid_eq: return "eq";
default: throw Exc_.new_unhandled(tid);
}
}
}

View File

@@ -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.gfs; import gplx.*;
public class Gfs_msg_bldr implements GfoMsgParser {
Gfs_parser parser = new Gfs_parser();
public GfoMsg ParseToMsg(String s) {return Bld(s);}
public GfoMsg Bld(String src) {return Bld(Bry_.new_u8(src));}
public GfoMsg Bld(byte[] src) {
Gfs_nde nde = parser.Parse(src);
return Bld_msg(src, nde);
}
GfoMsg Bld_msg(byte[] src, Gfs_nde nde) {
boolean op_is_assign = (nde.Op_tid() == Gfs_nde.Op_tid_assign);
String name = String_.new_u8(nde.Name_bry(src));
if (op_is_assign) name += Tkn_mutator;
GfoMsg rv = GfoMsg_.new_parse_(name);
int len = nde.Atrs_len();
for (int i = 0; i < len; i++) {
Gfs_nde atr = nde.Atrs_get_at(i);
rv.Add("", String_.new_u8(atr.Name_bry(src)));
}
len = nde.Subs_len();
for (int i = 0; i < len; i++) {
Gfs_nde sub = nde.Subs_get_at(i);
if (op_is_assign) // NOTE: for now (a) assignss cannot be nested; EX: "a.b = c;" is okay but "a.b = c.d;" is not
rv.Add("", Bld_msg(src, sub).Key());
else
rv.Subs_add(Bld_msg(src, sub));
}
return rv;
}
public static final Gfs_msg_bldr _ = new Gfs_msg_bldr(); Gfs_msg_bldr() {}
public static final String Tkn_mutator = "_";
}

View File

@@ -0,0 +1,76 @@
/*
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.gfs; import gplx.*;
import org.junit.*; import gplx.core.strings.*;
public class Gfs_msg_bldr_tst {
@Before public void init() {fxt.Clear();} Gfs_msg_bldr_fxt fxt = new Gfs_msg_bldr_fxt();
@Test public void Basic() {
fxt.Test_build("a;", fxt.msg_("a"));
}
@Test public void Dot() {
fxt.Test_build("a.b.c;"
, fxt.msg_("a").Subs_
( fxt.msg_("b").Subs_
( fxt.msg_("c")
)));
}
@Test public void Args() {
fxt.Test_build("a('b', 'c');", fxt.msg_("a", fxt.kv_("", "b"), fxt.kv_("", "c")));
}
@Test public void Args_num() {
fxt.Test_build("a(1);", fxt.msg_("a", fxt.kv_("", "1")));
}
@Test public void Assign() {
fxt.Test_build("a = 'b';", fxt.msg_("a_", fxt.kv_("", "b")));
}
@Test public void Assign_num() {
fxt.Test_build("a = 1;", fxt.msg_("a_", fxt.kv_("", "1")));
}
}
class Gfs_msg_bldr_fxt {
public void Clear() {} String_bldr sb = String_bldr_.new_(); Gfs_msg_bldr msg_bldr = Gfs_msg_bldr._;
public KeyVal kv_(String key, String val) {return KeyVal_.new_(key, val);}
public GfoMsg msg_(String key, KeyVal... args) {
GfoMsg rv = GfoMsg_.new_parse_(key);
int len = args.length;
for (int i = 0; i < len; i++) {
KeyVal kv = args[i];
rv.Add(kv.Key(), kv.Val());
}
return rv;
}
public void Test_build(String raw, GfoMsg... expd) {
GfoMsg root = msg_bldr.Bld(raw);
Tfds.Eq_str_lines(Xto_str(expd), Xto_str(To_ary(root)));
}
GfoMsg[] To_ary(GfoMsg msg) {
int len = msg.Subs_count();
GfoMsg[] rv = new GfoMsg[len];
for (int i = 0; i < len; i++)
rv[i] = msg.Subs_getAt(i);
return rv;
}
String Xto_str(GfoMsg[] ary) {
int len = ary.length;
for (int i = 0; i < len; i++) {
if (i != 0) sb.Add_char_crlf();
sb.Add(ary[i].XtoStr());
}
return sb.Xto_str_and_clear();
}
}

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