mirror of
https://github.com/gnosygnu/xowa.git
synced 2026-03-02 03:49:30 +00:00
Embeddable: Fix if_exists (restore)
This commit is contained in:
26
100_core/src/gplx/langs/dsvs/DsvDataRdrOpts.java
Normal file
26
100_core/src/gplx/langs/dsvs/DsvDataRdrOpts.java
Normal 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.langs.dsvs; import gplx.*; import gplx.langs.*;
|
||||
import gplx.core.gfo_ndes.*;
|
||||
public class DsvDataRdrOpts {
|
||||
public boolean HasHeader() {return hasHeader;} public DsvDataRdrOpts HasHeader_(boolean val) {hasHeader = val; return this;} private boolean hasHeader = false;
|
||||
public String NewLineSep() {return newLineSep;} public DsvDataRdrOpts NewLineSep_(String val) {newLineSep = val; return this;} private String newLineSep = String_.CrLf;
|
||||
public String FldSep() {return fldSep;} public DsvDataRdrOpts FldSep_(String val) {fldSep = val; return this;} private String fldSep = ",";
|
||||
public GfoFldList Flds() {return flds;} public DsvDataRdrOpts Flds_(GfoFldList val) {flds = val; return this;} GfoFldList flds = GfoFldList_.Null;
|
||||
public static DsvDataRdrOpts new_() {return new DsvDataRdrOpts();} DsvDataRdrOpts() {}
|
||||
}
|
||||
248
100_core/src/gplx/langs/dsvs/DsvDataRdr_.java
Normal file
248
100_core/src/gplx/langs/dsvs/DsvDataRdr_.java
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
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.langs.dsvs; import gplx.*; import gplx.langs.*;
|
||||
import gplx.core.strings.*; import gplx.core.gfo_ndes.*; import gplx.core.stores.*; import gplx.core.type_xtns.*;
|
||||
import gplx.core.texts.*; /*CharStream*/
|
||||
public class DsvDataRdr_ {
|
||||
public static DataRdr dsv_(String text) {return DsvParser.dsv_().ParseAsRdr(text);}
|
||||
public static DataRdr csv_hdr_(String text) {return csv_opts_(text, DsvDataRdrOpts.new_().HasHeader_(true));}
|
||||
public static DataRdr csv_dat_(String text) {return csv_opts_(text, DsvDataRdrOpts.new_());}
|
||||
public static DataRdr csv_dat_with_flds_(String text, String... flds) {return csv_opts_(text, DsvDataRdrOpts.new_().Flds_(GfoFldList_.str_(flds)));}
|
||||
public static DataRdr csv_opts_(String text, DsvDataRdrOpts opts) {
|
||||
DsvParser parser = DsvParser.csv_(opts.HasHeader(), opts.Flds()); // NOTE: this sets up the bldr; do not call .Init after this
|
||||
parser.Symbols().RowSep_(opts.NewLineSep()).FldSep_(opts.FldSep());
|
||||
|
||||
DataRdr root = parser.ParseAsRdr(text); // don't return root; callers expect csv to return rdr for rows
|
||||
DataRdr csvTable = root.Subs();
|
||||
return csvTable.Subs();
|
||||
}
|
||||
}
|
||||
class DsvParser {
|
||||
@gplx.Internal protected DsvSymbols Symbols() {return sym;} DsvSymbols sym = DsvSymbols.default_();
|
||||
@gplx.Internal protected void Init() {sb.Clear(); bldr.Init(); qteOn = false;}
|
||||
@gplx.Internal protected DataRdr ParseAsRdr(String raw) {return GfoNdeRdr_.root_(ParseAsNde(raw), csvOn);} // NOTE: csvOn means parse; assume manual typed flds not passed in (ex: id,Int)
|
||||
@gplx.Internal protected GfoNde ParseAsNde(String raw) {
|
||||
if (String_.Eq(raw, "")) return bldr.BldRoot();
|
||||
CharStream strm = CharStream.pos0_(raw);
|
||||
while (true) {
|
||||
if (strm.AtEnd()) {
|
||||
ProcessLine(strm, true);
|
||||
break;
|
||||
}
|
||||
if (qteOn)
|
||||
ReadStreamInQte(strm);
|
||||
else if (strm.MatchAndMove(sym.QteDlm()))
|
||||
qteOn = true;
|
||||
else if (strm.MatchAndMove(sym.FldSep()))
|
||||
ProcessFld(strm);
|
||||
else if (strm.MatchAndMove(sym.RowSep()))
|
||||
ProcessLine(strm, false);
|
||||
else {
|
||||
sb.Add(strm.Cur());
|
||||
strm.MoveNext();
|
||||
}
|
||||
}
|
||||
return bldr.BldRoot();
|
||||
}
|
||||
void ReadStreamInQte(CharStream strm) {
|
||||
if (strm.MatchAndMove(sym.QteDlm())) { // is quote
|
||||
if (strm.MatchAndMove(sym.QteDlm())) // double quote -> quote; "a""
|
||||
sb.Add(sym.QteDlm());
|
||||
else if (strm.MatchAndMove(sym.FldSep())) { // closing quote before field; "a",
|
||||
ProcessFld(strm);
|
||||
qteOn = false;
|
||||
}
|
||||
else if (strm.MatchAndMove(sym.RowSep()) || strm.AtEnd()) { // closing quote before record; "a"\r\n
|
||||
ProcessLine(strm, false);
|
||||
qteOn = false;
|
||||
}
|
||||
else
|
||||
throw Err_.new_wo_type("invalid quote in quoted field; quote must be followed by quote, fieldSpr, or recordSpr", "sym", strm.Cur(), "text", strm.To_str_by_pos(strm.Pos() - 10, strm.Pos() + 10));
|
||||
}
|
||||
else { // regular char; append and continue
|
||||
sb.Add(strm.Cur());
|
||||
strm.MoveNext();
|
||||
}
|
||||
}
|
||||
void ProcessFld(CharStream strm) {
|
||||
String val = sb.To_str_and_clear();
|
||||
if (cmdSeqOn) {
|
||||
cmdSeqOn = false;
|
||||
if (String_.Eq(val, sym.CmdDlm()) && qteOn) { // 2 cmdDlms in a row; cmdSeq encountered; next fld must be cmdName
|
||||
nextValType = ValType_CmdName;
|
||||
return;
|
||||
}
|
||||
tkns.Add(sym.CmdDlm()); // curTkn is not cmdDlm; prevTkn happened to be cmdDlm; add prev to tkns and continue; ex: a, ,b
|
||||
}
|
||||
if (String_.Eq(val, sym.CmdDlm())) // val is cmdDlm; do not add now; wait til next fld to decide
|
||||
cmdSeqOn = true;
|
||||
else if (nextValType == ValType_Data) {
|
||||
if (String_.Len(val) == 0) val = qteOn ? "" : null; // differentiate between null and emptyString; ,, vs ,"",
|
||||
tkns.Add(val);
|
||||
}
|
||||
else if (nextValType == ValType_CmdName) {
|
||||
if (String_.Eq(val, sym.TblNameSym())) lineMode = LineType_TblBgn; // #
|
||||
else if (String_.Eq(val, sym.FldNamesSym())) lineMode = LineType_FldNames; // @
|
||||
else if (String_.Eq(val, sym.FldTypesSym())) lineMode = LineType_FldTypes; // $
|
||||
else if (String_.Eq(val, sym.CommentSym())) lineMode = LineType_Comment; // '
|
||||
else throw Err_.new_wo_type("unknown dsv cmd", "cmd", val);
|
||||
}
|
||||
else
|
||||
throw Err_.new_wo_type("unable to process field value", "value", val);
|
||||
}
|
||||
void ProcessLine(CharStream strm, boolean cleanup) {
|
||||
if (sb.Count() == 0 && tkns.Count() == 0)
|
||||
if (csvOn) { // csvOn b/c csvMode allows blank lines as empty data
|
||||
if (cleanup) // cleanup b/c blankLine should not be added when called by cleanup, else will always add extra row at end
|
||||
return; // cleanup, so no further action needed; return;
|
||||
else
|
||||
ProcessFld(strm);
|
||||
}
|
||||
else
|
||||
lineMode = LineType_BlankLine;
|
||||
else
|
||||
ProcessFld(strm); // always process fld; either (1) chars waiting in sb "a,b"; or (2) last char was fldSep "a,"
|
||||
if (cmdSeqOn) { // only happens if last fld is comma space (, ); do not let cmds span lines
|
||||
cmdSeqOn = false;
|
||||
tkns.Add(sym.CmdDlm());
|
||||
}
|
||||
if (lineMode == LineType_TblBgn) bldr.MakeTblBgn(tkns);
|
||||
else if (lineMode == LineType_FldNames) bldr.MakeFldNames(tkns);
|
||||
else if (lineMode == LineType_FldTypes) bldr.MakeFldTypes(tkns);
|
||||
else if (lineMode == LineType_Comment) bldr.MakeComment(tkns);
|
||||
else if (lineMode == LineType_BlankLine) bldr.MakeBlankLine();
|
||||
else bldr.MakeVals(tkns);
|
||||
nextValType = ValType_Data;
|
||||
lineMode = LineType_Data;
|
||||
}
|
||||
String_bldr sb = String_bldr_.new_(); List_adp tkns = List_adp_.New(); DsvTblBldr bldr = DsvTblBldr.new_();
|
||||
boolean cmdSeqOn = false, qteOn = false, csvOn = false;
|
||||
int nextValType = ValType_Data, lineMode = LineType_Data;
|
||||
@gplx.Internal protected static DsvParser dsv_() {return new DsvParser();}
|
||||
@gplx.Internal protected static DsvParser csv_(boolean hasHdr, GfoFldList flds) {
|
||||
DsvParser rv = new DsvParser();
|
||||
rv.csvOn = true;
|
||||
rv.lineMode = hasHdr ? LineType_FldNames : LineType_Data;
|
||||
List_adp names = List_adp_.New(), types = List_adp_.New();
|
||||
for (int i = 0; i < flds.Count(); i++) {
|
||||
GfoFld fld = flds.Get_at(i);
|
||||
names.Add(fld.Key()); types.Add(fld.Type().Key());
|
||||
}
|
||||
rv.bldr.MakeFldNames(names); rv.bldr.MakeFldTypes(types);
|
||||
return rv;
|
||||
}
|
||||
static final int ValType_Data = 0, ValType_CmdName = 1;
|
||||
static final int LineType_Data = 0, LineType_Comment = 1, LineType_TblBgn = 2, LineType_FldNames = 3, LineType_FldTypes = 4, LineType_BlankLine = 5;
|
||||
}
|
||||
class DsvTblBldr {
|
||||
public void Init() {
|
||||
root = GfoNde_.root_(); tbl = GfoNde_.tbl_(NullTblName, GfoFldList_.new_());
|
||||
fldNames.Clear(); fldTypes.Clear();
|
||||
stage = Stage_Init;
|
||||
}
|
||||
public GfoNde BldRoot() {
|
||||
if (stage != Stage_Init) CreateTbl(); // CreateTbl if HDR or ROW is in progress
|
||||
return root;
|
||||
}
|
||||
public void MakeTblBgn(List_adp tkns) {
|
||||
if (stage != Stage_Init) CreateTbl(); // CreateTbl if HDR or ROW is in progress
|
||||
tbl.Name_((String)tkns.Get_at(0));
|
||||
layout.HeaderList().Add_TableName();
|
||||
stage = Stage_Hdr; tkns.Clear();
|
||||
}
|
||||
public void MakeFldNames(List_adp tkns) {
|
||||
if (stage == Stage_Row) CreateTbl(); // CreateTbl if ROW is in progress; NOTE: exclude HDR, as first HDR would have called CreateTbl
|
||||
fldNames.Clear();
|
||||
for (Object fldNameObj : tkns)
|
||||
fldNames.Add(fldNameObj);
|
||||
layout.HeaderList().Add_LeafNames();
|
||||
stage = Stage_Hdr; tkns.Clear();
|
||||
}
|
||||
public void MakeFldTypes(List_adp tkns) {
|
||||
if (stage == Stage_Row) CreateTbl(); // CreateTbl if ROW is in progress; NOTE: exclude HDR, as first HDR would have called CreateTbl
|
||||
fldTypes.Clear();
|
||||
for (Object fldTypeObj : tkns) {
|
||||
ClassXtn type = ClassXtnPool.Instance.Get_by_or_fail((String)fldTypeObj);
|
||||
fldTypes.Add(type);
|
||||
}
|
||||
layout.HeaderList().Add_LeafTypes();
|
||||
stage = Stage_Hdr; tkns.Clear();
|
||||
}
|
||||
public void MakeComment(List_adp tkns) {
|
||||
if (stage == Stage_Row) // comments in ROW; ignore; NOTE: tkns.Clear() could be merged, but this seems clearer
|
||||
tkns.Clear();
|
||||
else { // comments in HDR
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
for (int i = 0; i < tkns.Count(); i++)
|
||||
sb.Add((String)tkns.Get_at(i));
|
||||
layout.HeaderList().Add_Comment(sb.To_str());
|
||||
tkns.Clear();
|
||||
}
|
||||
}
|
||||
public void MakeBlankLine() {
|
||||
if (stage != Stage_Init) CreateTbl(); // CreateTbl if HDR or ROW is in progress;
|
||||
layout.HeaderList().Add_BlankLine();
|
||||
stage = Stage_Init; // NOTE: mark stage as INIT;
|
||||
}
|
||||
public void MakeVals(List_adp tkns) {
|
||||
if (stage != Stage_Row) CreateFlds(tkns.Count()); // stage != Stage_Row means if (noRowsCreated)
|
||||
GfoNde row = GfoNde_.vals_(tbl.SubFlds(), MakeValsAry(tkns));
|
||||
tbl.Subs().Add(row);
|
||||
stage = Stage_Row; tkns.Clear();
|
||||
}
|
||||
Object[] MakeValsAry(List_adp tkns) {
|
||||
GfoFldList subFlds = tbl.SubFlds(); int subFldsCount = subFlds.Count();
|
||||
if (tkns.Count() > subFldsCount) throw Err_.new_wo_type("values.Count cannot be greater than fields.Count", "values.Count", tkns.Count(), "fields.Count", subFldsCount);
|
||||
Object[] rv = new Object[subFldsCount];
|
||||
for (int i = 0; i < subFldsCount; i++) {
|
||||
ClassXtn typx = subFlds.Get_at(i).Type();
|
||||
String val = i < tkns.Count() ? (String)tkns.Get_at(i) : null;
|
||||
rv[i] = typx.ParseOrNull(val);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
void CreateTbl() {
|
||||
if (tbl.SubFlds().Count() == 0) CreateFlds(0); // this check occurs when tbl has no ROW; (TOMB: tdb test fails)
|
||||
tbl.EnvVars().Add(DsvStoreLayout.Key_const, layout);
|
||||
root.Subs().Add(tbl); // add pending table
|
||||
layout = DsvStoreLayout.dsv_brief_();
|
||||
tbl = GfoNde_.tbl_(NullTblName, GfoFldList_.new_());
|
||||
stage = Stage_Hdr;
|
||||
}
|
||||
void CreateFlds(int valCount) {
|
||||
int fldNamesCount = fldNames.Count(), fldTypesCount = fldTypes.Count();
|
||||
if (fldNamesCount == 0 && fldTypesCount == 0) { // csv tbls where no names or types, just values
|
||||
for (int i = 0; i < valCount; i++)
|
||||
tbl.SubFlds().Add("fld" + i, StringClassXtn.Instance);
|
||||
}
|
||||
else { // all else, where either names or types is defined
|
||||
int maxCount = fldNamesCount > fldTypesCount ? fldNamesCount : fldTypesCount;
|
||||
for (int i = 0; i < maxCount; i++) {
|
||||
String name = i < fldNamesCount ? (String)fldNames.Get_at(i) : "fld" + i;
|
||||
ClassXtn typx = i < fldTypesCount ? (ClassXtn)fldTypes.Get_at(i) : StringClassXtn.Instance;
|
||||
tbl.SubFlds().Add(name, typx);
|
||||
}
|
||||
}
|
||||
}
|
||||
GfoNde root; GfoNde tbl; DsvStoreLayout layout = DsvStoreLayout.dsv_brief_();
|
||||
List_adp fldNames = List_adp_.New(); List_adp fldTypes = List_adp_.New();
|
||||
int stage = Stage_Init;
|
||||
public static DsvTblBldr new_() {return new DsvTblBldr();} DsvTblBldr() {this.Init();}
|
||||
@gplx.Internal protected static final String NullTblName = "";
|
||||
static final int Stage_Init = 0, Stage_Hdr = 1, Stage_Row = 2;
|
||||
}
|
||||
216
100_core/src/gplx/langs/dsvs/DsvDataRdr_csv_dat_tst.java
Normal file
216
100_core/src/gplx/langs/dsvs/DsvDataRdr_csv_dat_tst.java
Normal file
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
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.langs.dsvs; import gplx.*; import gplx.langs.*;
|
||||
import org.junit.*; import gplx.core.strings.*; import gplx.core.gfo_ndes.*;
|
||||
public class DsvDataRdr_csv_dat_tst {
|
||||
@Before public void setup() {
|
||||
fx.Parser_(DsvParser.csv_(false, GfoFldList_.Null));
|
||||
fx.Clear();
|
||||
} DsvDataRdr_fxt fx = DsvDataRdr_fxt.new_();
|
||||
@Test public void Empty() {
|
||||
fx.run_parse_("");
|
||||
fx.tst_DatNull();
|
||||
}
|
||||
@Test public void Fld_0() {
|
||||
fx.run_parse_("a");
|
||||
fx.tst_DatCsv(fx.ary_("a"));
|
||||
}
|
||||
@Test public void Fld_N() {
|
||||
fx.run_parse_("a,b,c");
|
||||
fx.tst_FldListCsv("fld0", "fld1", "fld2");
|
||||
fx.tst_DatCsv(fx.ary_("a", "b", "c"));
|
||||
}
|
||||
@Test public void Row_N() {
|
||||
fx.run_parse_
|
||||
( "a,b,c", String_.CrLf
|
||||
, "1,2,3"
|
||||
);
|
||||
fx.tst_DatCsv
|
||||
( fx.ary_("a", "b", "c")
|
||||
, fx.ary_("1", "2", "3")
|
||||
);
|
||||
}
|
||||
@Test public void Escape_WhiteSpace() {
|
||||
fx.run_parse_("a,\" \t\",c");
|
||||
fx.tst_DatCsv(fx.ary_("a", " \t", "c"));
|
||||
}
|
||||
@Test public void Escape_FldSep() {
|
||||
fx.run_parse_("a,\",\",c");
|
||||
fx.tst_DatCsv(fx.ary_("a", ",", "c"));
|
||||
}
|
||||
@Test public void Escape_RowSep() {
|
||||
fx.run_parse_("a,\"" + String_.CrLf + "\",c");
|
||||
fx.tst_DatCsv(fx.ary_("a", String_.CrLf, "c"));
|
||||
}
|
||||
@Test public void Escape_Quote() {
|
||||
fx.run_parse_("a,\"\"\"\",c");
|
||||
fx.tst_DatCsv(fx.ary_("a", "\"", "c"));
|
||||
}
|
||||
@Test public void Blank_Null() {
|
||||
fx.run_parse_("a,,c");
|
||||
fx.tst_DatCsv(fx.ary_("a", null, "c"));
|
||||
}
|
||||
@Test public void Blank_EmptyString() {
|
||||
fx.run_parse_("a,\"\",c");
|
||||
fx.tst_DatCsv(fx.ary_("a", "", "c"));
|
||||
}
|
||||
@Test public void Blank_Null_Multiple() {
|
||||
fx.run_parse_(",,");
|
||||
fx.tst_DatCsv(fx.ary_(null, null, null));
|
||||
}
|
||||
@Test public void TrailingNull() {
|
||||
fx.run_parse_("a,");
|
||||
fx.tst_DatCsv(fx.ary_("a", null));
|
||||
}
|
||||
@Test public void TrailingEmpty() {
|
||||
fx.run_parse_("a,\"\"");
|
||||
fx.tst_DatCsv(fx.ary_("a", ""));
|
||||
}
|
||||
@Test public void Quote_Error() {
|
||||
try {
|
||||
fx.run_parse_("a,\"\" ,c");
|
||||
Tfds.Fail_expdError();
|
||||
}
|
||||
catch (Err e) {
|
||||
Tfds.Eq_true(String_.Has(Err_.Message_lang(e), "invalid quote in quoted field"));
|
||||
}
|
||||
}
|
||||
@Test public void Misc_AllowValsLessThanFields() {
|
||||
// assume null when vals.Count < fields.Count; PURPOSE: MsExcel will not save trailing commas for csvExport; ex: a, -> a
|
||||
fx.run_parse_
|
||||
( "a0,a1", String_.CrLf
|
||||
, "b0"
|
||||
);
|
||||
fx.tst_DatCsv
|
||||
( fx.ary_("a0", "a1")
|
||||
, fx.ary_("b0", null)
|
||||
);
|
||||
}
|
||||
@Test public void Misc_NewLineValidForSingleColumnTables() {
|
||||
fx.run_parse_
|
||||
( "a", String_.CrLf
|
||||
, String_.CrLf
|
||||
, "c" , String_.CrLf
|
||||
, String_.CrLf
|
||||
);
|
||||
fx.tst_DatCsv
|
||||
( fx.ary_("a")
|
||||
, fx.ary_null_()
|
||||
, fx.ary_("c")
|
||||
, fx.ary_null_()
|
||||
);
|
||||
}
|
||||
@Test public void Misc_NewLineValidForSingleColumnTables_FirstLine() {
|
||||
fx.run_parse_
|
||||
( String_.CrLf
|
||||
, "b", String_.CrLf
|
||||
, "c"
|
||||
);
|
||||
fx.tst_DatCsv
|
||||
( fx.ary_null_()
|
||||
, fx.ary_("b")
|
||||
, fx.ary_("c")
|
||||
);
|
||||
}
|
||||
@Test public void Hdr_Basic() {
|
||||
fx.Parser_(DsvParser.csv_(true, GfoFldList_.Null));
|
||||
fx.run_parse_
|
||||
( "id,name", String_.CrLf
|
||||
, "0,me"
|
||||
);
|
||||
fx.tst_FldListCsv("id", "name");
|
||||
fx.tst_DatCsv(fx.ary_("0", "me"));
|
||||
}
|
||||
// @Test public void Hdr_Manual() {
|
||||
// fx.Parser_(DsvParser.csv_(false, GfoFldList_.new_().Add("id", IntClassXtn.Instance).Add("name", StringClassXtn.Instance), true));
|
||||
// fx.run_parse_("0,me");
|
||||
// fx.tst_DatCsv(fx.ary_(0, "me")); // NOTE: testing auto-parsing of id to int b/c id fld is IntClassXtn.Instance;
|
||||
// }
|
||||
}
|
||||
class DsvDataRdr_fxt {
|
||||
public Object[] ary_(Object... ary) {return ary;}
|
||||
public Object[] ary_null_() {return new Object[] {null};}
|
||||
public void Clear() {parser.Init(); root = null;}
|
||||
public DsvParser Parser() {return parser;} public DsvDataRdr_fxt Parser_(DsvParser val) {parser = val; return this;} DsvParser parser = DsvParser.dsv_();
|
||||
public GfoNde Root() {return root;} GfoNde root;
|
||||
public void run_parse_(String... ary) {root = parser.ParseAsNde(String_.Concat(ary));}
|
||||
public void run_parse_lines_(String... ary) {root = parser.ParseAsNde(String_.Concat_lines_crlf(ary));}
|
||||
public DsvDataRdr_fxt tst_FldListCsv(String... names) {return tst_Flds(TblIdx0, GfoFldList_.str_(names));}
|
||||
public DsvDataRdr_fxt tst_Flds(int tblIdx, GfoFldList expdFlds) {
|
||||
GfoNde tbl = root.Subs().FetchAt_asGfoNde(tblIdx);
|
||||
List_adp expdList = List_adp_.New(), actlList = List_adp_.New();
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
GfoFldList_BldDbgList(expdFlds, expdList, sb);
|
||||
GfoFldList_BldDbgList(tbl.SubFlds(), actlList, sb);
|
||||
Tfds.Eq_list(expdList, actlList);
|
||||
return this;
|
||||
}
|
||||
void GfoFldList_BldDbgList(GfoFldList flds, List_adp list, String_bldr sb) {
|
||||
for (int i = 0; i < flds.Count(); i++) {
|
||||
GfoFld fld = flds.Get_at(i);
|
||||
sb.Add(fld.Key()).Add(",").Add(fld.Type().Key());
|
||||
list.Add(sb.To_str_and_clear());
|
||||
}
|
||||
}
|
||||
public DsvDataRdr_fxt tst_Tbls(String... expdNames) {
|
||||
List_adp actlList = List_adp_.New();
|
||||
for (int i = 0; i < root.Subs().Count(); i++) {
|
||||
GfoNde tbl = root.Subs().FetchAt_asGfoNde(i);
|
||||
actlList.Add(tbl.Name());
|
||||
}
|
||||
Tfds.Eq_ary(expdNames, actlList.To_str_ary());
|
||||
return this;
|
||||
}
|
||||
public DsvDataRdr_fxt tst_DatNull() {
|
||||
Tfds.Eq(0, root.Subs().Count());
|
||||
return this;
|
||||
}
|
||||
public DsvDataRdr_fxt tst_DatCsv(Object[]... expdRows) {return tst_Dat(0, expdRows);}
|
||||
public DsvDataRdr_fxt tst_Dat(int tblIdx, Object[]... expdRows) {
|
||||
GfoNde tbl = root.Subs().FetchAt_asGfoNde(tblIdx);
|
||||
if (expdRows.length == 0) {
|
||||
Tfds.Eq(0, tbl.Subs().Count());
|
||||
return this;
|
||||
}
|
||||
List_adp expdList = List_adp_.New(), actlList = List_adp_.New();
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
for (int i = 0; i < tbl.Subs().Count(); i++) {
|
||||
GfoNde row = tbl.Subs().FetchAt_asGfoNde(i);
|
||||
for (int j = 0; j < row.Flds().Count(); j++) {
|
||||
if (j != 0) sb.Add("~");
|
||||
sb.Add_obj(Object_.Xto_str_strict_or_null_mark(row.ReadAt(j)));
|
||||
}
|
||||
expdList.Add(sb.To_str_and_clear());
|
||||
}
|
||||
for (Object[] expdRow : expdRows) {
|
||||
if (expdRow == null) {
|
||||
actlList.Add("");
|
||||
continue;
|
||||
}
|
||||
for (int j = 0; j < expdRow.length; j++) {
|
||||
if (j != 0) sb.Add("~");
|
||||
sb.Add_obj(Object_.Xto_str_strict_or_null_mark(expdRow[j]));
|
||||
}
|
||||
actlList.Add(sb.To_str_and_clear());
|
||||
}
|
||||
Tfds.Eq_list(expdList, actlList);
|
||||
return this;
|
||||
}
|
||||
public static DsvDataRdr_fxt new_() {return new DsvDataRdr_fxt();}
|
||||
static final int TblIdx0 = 0;
|
||||
}
|
||||
70
100_core/src/gplx/langs/dsvs/DsvDataRdr_dsv_dat_tst.java
Normal file
70
100_core/src/gplx/langs/dsvs/DsvDataRdr_dsv_dat_tst.java
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
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.langs.dsvs; import gplx.*; import gplx.langs.*;
|
||||
import org.junit.*;
|
||||
public class DsvDataRdr_dsv_dat_tst {
|
||||
@Before public void setup() {fx.Clear();} DsvDataRdr_fxt fx = DsvDataRdr_fxt.new_();
|
||||
@Test public void NameOnly() {
|
||||
fx.run_parse_("tableName, ,\" \",#");
|
||||
fx.tst_Tbls("tableName");
|
||||
fx.tst_Dat(0);
|
||||
}
|
||||
@Test public void Rows_N() {
|
||||
fx.run_parse_lines_
|
||||
( "numbers, ,\" \",#"
|
||||
, "1,2,3"
|
||||
, "4,5,6"
|
||||
);
|
||||
fx.tst_Tbls("numbers");
|
||||
fx.tst_Dat(0
|
||||
, fx.ary_("1", "2", "3")
|
||||
, fx.ary_("4", "5", "6")
|
||||
);
|
||||
}
|
||||
@Test public void Tbls_N() {
|
||||
fx.run_parse_lines_
|
||||
( "letters, ,\" \",#"
|
||||
, "a,b,c"
|
||||
, "numbers, ,\" \",#"
|
||||
, "1,2,3"
|
||||
, "4,5,6"
|
||||
);
|
||||
fx.tst_Tbls("letters", "numbers");
|
||||
fx.tst_Dat(0, fx.ary_("a", "b", "c"));
|
||||
fx.tst_Dat(1, fx.ary_("1", "2", "3"), fx.ary_("4", "5", "6"));
|
||||
}
|
||||
@Test public void IgnoreTrailingBlankRow() {
|
||||
fx.run_parse_lines_
|
||||
( "letters, ,\" \",#"
|
||||
, "a,b,c"
|
||||
, "" // ignored
|
||||
);
|
||||
fx.tst_Tbls("letters");
|
||||
fx.tst_Dat(0, fx.ary_("a", "b", "c"));
|
||||
}
|
||||
@Test public void AllowCommentsDuringData() {
|
||||
fx.run_parse_lines_
|
||||
( "letters, ,\" \",#"
|
||||
, "a,b,c"
|
||||
, "// letters omitted, ,\" \",//" // these comments are not preserved
|
||||
, "x,y,z"
|
||||
);
|
||||
fx.tst_Tbls("letters");
|
||||
fx.tst_Dat(0, fx.ary_("a", "b", "c"), fx.ary_("x", "y", "z"));
|
||||
}
|
||||
}
|
||||
82
100_core/src/gplx/langs/dsvs/DsvDataRdr_dsv_hdr_tst.java
Normal file
82
100_core/src/gplx/langs/dsvs/DsvDataRdr_dsv_hdr_tst.java
Normal 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.langs.dsvs; import gplx.*; import gplx.langs.*;
|
||||
import org.junit.*; import gplx.core.gfo_ndes.*; import gplx.core.type_xtns.*;
|
||||
public class DsvDataRdr_dsv_hdr_tst {
|
||||
@Before public void setup() {fx.Clear();} DsvDataRdr_fxt fx = DsvDataRdr_fxt.new_();
|
||||
@Test public void Names() {
|
||||
fx.run_parse_lines_
|
||||
( "id,name, ,\" \",@"
|
||||
, "0,me"
|
||||
, "1,you"
|
||||
);
|
||||
fx.tst_Flds(0, GfoFldList_.str_("id", "name"));
|
||||
fx.tst_Tbls(DsvTblBldr.NullTblName);
|
||||
fx.tst_Dat(0
|
||||
, fx.ary_("0", "me")
|
||||
, fx.ary_("1", "you")
|
||||
);
|
||||
}
|
||||
@Test public void Types() {
|
||||
fx.run_parse_lines_
|
||||
( "int," + StringClassXtn.Key_const + ", ,\" \",$"
|
||||
, "0,me"
|
||||
, "1,you"
|
||||
);
|
||||
fx.tst_Flds(0, GfoFldList_.new_().Add("fld0", IntClassXtn.Instance).Add("fld1", StringClassXtn.Instance));
|
||||
fx.tst_Dat(0
|
||||
, fx.ary_(0, "me")
|
||||
, fx.ary_(1, "you")
|
||||
);
|
||||
}
|
||||
@Test public void NamesAndTypes() {
|
||||
fx.run_parse_lines_
|
||||
( "id,name, ,\" \",@"
|
||||
, "int," + StringClassXtn.Key_const + ", ,\" \",$"
|
||||
, "0,me"
|
||||
, "1,you"
|
||||
);
|
||||
fx.tst_Flds(0, GfoFldList_.new_().Add("id", IntClassXtn.Instance).Add("name", StringClassXtn.Instance));
|
||||
fx.tst_Dat(0
|
||||
, fx.ary_(0, "me")
|
||||
, fx.ary_(1, "you")
|
||||
);
|
||||
}
|
||||
@Test public void MultipleTables_NoData() {
|
||||
fx.run_parse_lines_
|
||||
( "persons, ,\" \",#"
|
||||
, "id,name, ,\" \",@"
|
||||
, "things, ,\" \",#"
|
||||
, "id,data, ,\" \",@"
|
||||
);
|
||||
fx.tst_Tbls("persons", "things");
|
||||
fx.tst_Flds(0, GfoFldList_.str_("id", "name"));
|
||||
fx.tst_Flds(1, GfoFldList_.str_("id", "data"));
|
||||
fx.tst_Dat(0);
|
||||
fx.tst_Dat(1);
|
||||
}
|
||||
@Test public void Comment() {
|
||||
fx.run_parse_lines_
|
||||
( "--------------------, ,\" \",//"
|
||||
, "tbl0, ,\" \",#"
|
||||
, "a0,a1"
|
||||
);
|
||||
fx.tst_Tbls("tbl0");
|
||||
fx.tst_Dat(0, fx.ary_("a0", "a1"));
|
||||
}
|
||||
}
|
||||
76
100_core/src/gplx/langs/dsvs/DsvDataRdr_dsv_misc_tst.java
Normal file
76
100_core/src/gplx/langs/dsvs/DsvDataRdr_dsv_misc_tst.java
Normal 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.langs.dsvs; import gplx.*; import gplx.langs.*;
|
||||
import org.junit.*; import gplx.core.gfo_ndes.*; import gplx.core.type_xtns.*;
|
||||
public class DsvDataRdr_dsv_misc_tst {
|
||||
@Before public void setup() {fx.Clear();} DsvDataRdr_fxt fx = DsvDataRdr_fxt.new_();
|
||||
@Test public void CmdDlm_NearMatches() {
|
||||
fx.run_parse_("a, ,b");
|
||||
fx.tst_DatCsv(fx.ary_("a", " ", "b"));
|
||||
fx.Clear();
|
||||
|
||||
fx.run_parse_("a,\" \",b");
|
||||
fx.tst_DatCsv(fx.ary_("a", " ", "b"));
|
||||
fx.Clear();
|
||||
|
||||
fx.run_parse_("a, ,b,\" \",c");
|
||||
fx.tst_DatCsv(fx.ary_("a", " ", "b", " ", "c"));
|
||||
fx.Clear();
|
||||
}
|
||||
@Test public void CmdDlm_DoNotSpanLines() {
|
||||
fx.run_parse_lines_
|
||||
( "a, "
|
||||
, "\" \",b"
|
||||
);
|
||||
fx.tst_DatCsv
|
||||
( fx.ary_("a", " ")
|
||||
, fx.ary_(" ", "b")
|
||||
);
|
||||
}
|
||||
@Test public void CmdDlm_SecondFldMustBeQuoted() {
|
||||
fx.run_parse_lines_("a, , ,b"); // will fail with "invalid command: b", if second , , is interpreted as command delimiter
|
||||
fx.tst_DatCsv(fx.ary_("a", " ", " ", "b"));
|
||||
}
|
||||
@Test public void Null_Int() {
|
||||
fx.run_parse_ // not using run_parse_lines_ b/c (a) will have extra lineBreak; (b) test will look funny;
|
||||
( "int," + StringClassXtn.Key_const + ", ,\" \",$", String_.CrLf
|
||||
, ",val1"
|
||||
);
|
||||
fx.tst_Tbls(DsvTblBldr.NullTblName);
|
||||
fx.tst_Flds(0, GfoFldList_.new_().Add("fld0", IntClassXtn.Instance).Add("fld1", StringClassXtn.Instance));
|
||||
fx.tst_Dat(0, fx.ary_(null, "val1"));
|
||||
}
|
||||
@Test public void Null_String() {
|
||||
fx.run_parse_ // not using run_parse_lines_ b/c (a) will have extra lineBreak; (b) test will look funny;
|
||||
( StringClassXtn.Key_const + "," + StringClassXtn.Key_const + ", ,\" \",$", String_.CrLf
|
||||
, ",val1"
|
||||
);
|
||||
fx.tst_Tbls(DsvTblBldr.NullTblName);
|
||||
fx.tst_Flds(0, GfoFldList_.new_().Add("fld0", StringClassXtn.Instance).Add("fld1", StringClassXtn.Instance));
|
||||
fx.tst_Dat(0, fx.ary_(null, "val1"));
|
||||
}
|
||||
@Test public void EmptyString() {
|
||||
fx.run_parse_ // not using run_parse_lines_ b/c (a) will have extra lineBreak; (b) test will look funny;
|
||||
( StringClassXtn.Key_const + "," + StringClassXtn.Key_const + ", ,\" \",$", String_.CrLf
|
||||
, "\"\",val1"
|
||||
);
|
||||
fx.tst_Tbls(DsvTblBldr.NullTblName);
|
||||
fx.tst_Flds(0, GfoFldList_.new_().Add("fld0", StringClassXtn.Instance).Add("fld1", StringClassXtn.Instance));
|
||||
fx.tst_Dat(0, fx.ary_("", "val1"));
|
||||
}
|
||||
}
|
||||
131
100_core/src/gplx/langs/dsvs/DsvDataRdr_layout_tst.java
Normal file
131
100_core/src/gplx/langs/dsvs/DsvDataRdr_layout_tst.java
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
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.langs.dsvs; import gplx.*; import gplx.langs.*;
|
||||
import org.junit.*; import gplx.core.gfo_ndes.*; import gplx.core.type_xtns.*;
|
||||
public class DsvDataRdr_layout_tst {
|
||||
@Test public void TableName() {
|
||||
run_parse_lines("table0, ,\" \",#");
|
||||
tst_Layout(0, DsvHeaderItm.Id_TableName);
|
||||
}
|
||||
@Test public void Comment() {
|
||||
run_parse_lines("-------------, ,\" \",//", "data"); // need dataLine or parser will throw away standalone header
|
||||
tst_Layout(0, DsvHeaderItm.Id_Comment);
|
||||
}
|
||||
@Test public void BlankLine() {
|
||||
run_parse_lines("", "data"); // need dataLine or parser will throw away standalone header
|
||||
tst_Layout(0, DsvHeaderItm.Id_BlankLine);
|
||||
}
|
||||
@Test public void LeafNames() {
|
||||
run_parse_lines("id,name, ,\" \",@");
|
||||
tst_Layout(0, DsvHeaderItm.Id_LeafNames);
|
||||
}
|
||||
@Test public void LeafTypes() {
|
||||
run_parse_lines("int," + StringClassXtn.Key_const + ", ,\" \",$");
|
||||
tst_Layout(0, DsvHeaderItm.Id_LeafTypes);
|
||||
}
|
||||
@Test public void Combined() {
|
||||
run_parse_lines
|
||||
( ""
|
||||
, "-------------, ,\" \",//"
|
||||
, "table0, ,\" \",#"
|
||||
, "int," + StringClassXtn.Key_const + ", ,\" \",$"
|
||||
, "id,name, ,\" \",@"
|
||||
, "-------------, ,\" \",//"
|
||||
, "0,me"
|
||||
);
|
||||
tst_Layout(0
|
||||
, DsvHeaderItm.Id_BlankLine
|
||||
, DsvHeaderItm.Id_Comment
|
||||
, DsvHeaderItm.Id_TableName
|
||||
, DsvHeaderItm.Id_LeafTypes
|
||||
, DsvHeaderItm.Id_LeafNames
|
||||
, DsvHeaderItm.Id_Comment
|
||||
);
|
||||
}
|
||||
@Test public void Tbl_N() {
|
||||
run_parse_lines
|
||||
( ""
|
||||
, "*************, ,\" \",//"
|
||||
, "table0, ,\" \",#"
|
||||
, "-------------, ,\" \",//"
|
||||
, "0,me"
|
||||
, ""
|
||||
, "*************, ,\" \",//"
|
||||
, "table1, ,\" \",#"
|
||||
, " extended data, ,\" \",//"
|
||||
, "-------------, ,\" \",//"
|
||||
, "1,you,more"
|
||||
);
|
||||
tst_Layout(0
|
||||
, DsvHeaderItm.Id_BlankLine
|
||||
, DsvHeaderItm.Id_Comment
|
||||
, DsvHeaderItm.Id_TableName
|
||||
, DsvHeaderItm.Id_Comment
|
||||
);
|
||||
tst_Layout(1
|
||||
, DsvHeaderItm.Id_BlankLine
|
||||
, DsvHeaderItm.Id_Comment
|
||||
, DsvHeaderItm.Id_TableName
|
||||
, DsvHeaderItm.Id_Comment
|
||||
, DsvHeaderItm.Id_Comment
|
||||
);
|
||||
}
|
||||
@Test public void Tbl_N_FirstIsEmpty() {
|
||||
run_parse_lines
|
||||
( ""
|
||||
, "*************, ,\" \",//"
|
||||
, "table0, ,\" \",#"
|
||||
, "-------------, ,\" \",//"
|
||||
, ""
|
||||
, ""
|
||||
, "*************, ,\" \",//"
|
||||
, "table1, ,\" \",#"
|
||||
, " extended data, ,\" \",//"
|
||||
, "-------------, ,\" \",//"
|
||||
, "1,you,more"
|
||||
);
|
||||
tst_Layout(0
|
||||
, DsvHeaderItm.Id_BlankLine
|
||||
, DsvHeaderItm.Id_Comment
|
||||
, DsvHeaderItm.Id_TableName
|
||||
, DsvHeaderItm.Id_Comment
|
||||
);
|
||||
tst_Layout(1
|
||||
, DsvHeaderItm.Id_BlankLine
|
||||
, DsvHeaderItm.Id_BlankLine
|
||||
, DsvHeaderItm.Id_Comment
|
||||
, DsvHeaderItm.Id_TableName
|
||||
, DsvHeaderItm.Id_Comment
|
||||
, DsvHeaderItm.Id_Comment
|
||||
);
|
||||
}
|
||||
void run_parse_lines(String... ary) {
|
||||
String raw = String_.Concat_lines_crlf(ary);
|
||||
DsvParser parser = DsvParser.dsv_();
|
||||
root = parser.ParseAsNde(raw);
|
||||
}
|
||||
void tst_Layout(int subIdx, int... expd) {
|
||||
GfoNde tbl = root.Subs().FetchAt_asGfoNde(subIdx);
|
||||
DsvStoreLayout layout = (DsvStoreLayout)tbl.EnvVars().Get_by(DsvStoreLayout.Key_const);
|
||||
int[] actl = new int[layout.HeaderList().Count()];
|
||||
for (int i = 0; i < actl.length; i++)
|
||||
actl[i] = layout.HeaderList().Get_at(i).Id();
|
||||
Tfds.Eq_ary(expd, actl);
|
||||
}
|
||||
GfoNde root;
|
||||
}
|
||||
115
100_core/src/gplx/langs/dsvs/DsvDataWtr.java
Normal file
115
100_core/src/gplx/langs/dsvs/DsvDataWtr.java
Normal 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.langs.dsvs; import gplx.*; import gplx.langs.*;
|
||||
import gplx.core.strings.*; import gplx.core.gfo_ndes.*; import gplx.core.stores.*;
|
||||
public class DsvDataWtr extends DataWtr_base implements DataWtr {
|
||||
public void InitWtr(String key, Object val) {
|
||||
if (key == DsvStoreLayout.Key_const) layout = (DsvStoreLayout)val;
|
||||
}
|
||||
@Override public void WriteData(String name, Object val) {sb.WriteFld(val == null ? null : val.toString());}
|
||||
public void WriteLeafBgn(String leafName) {}
|
||||
public void WriteLeafEnd() {sb.WriteRowSep();}
|
||||
@Override public void WriteNodeBgn(String name) {WriteTableBgn(name, GfoFldList_.Null);}
|
||||
public void WriteTableBgn(String name, GfoFldList flds) {
|
||||
for (int i = 0; i < layout.HeaderList().Count(); i++) {
|
||||
DsvHeaderItm data = layout.HeaderList().Get_at(i);
|
||||
int id = data.Id();
|
||||
if (id == DsvHeaderItm.Id_TableName) WriteTableName(name);
|
||||
else if (id == DsvHeaderItm.Id_LeafNames) WriteMeta(flds, true, sym.FldNamesSym());
|
||||
else if (id == DsvHeaderItm.Id_LeafTypes) WriteMeta(flds, false, sym.FldTypesSym());
|
||||
else if (id == DsvHeaderItm.Id_BlankLine) sb.WriteRowSep();
|
||||
else if (id == DsvHeaderItm.Id_Comment) WriteComment(data.Val().toString());
|
||||
}
|
||||
}
|
||||
@Override public void WriteNodeEnd() {}
|
||||
public void Clear() {sb.Clear();}
|
||||
public String To_str() {return sb.To_str();}
|
||||
void WriteTableName(String tableName) {
|
||||
sb.WriteFld(tableName);
|
||||
sb.WriteCmd(sym.TblNameSym());
|
||||
sb.WriteRowSep();
|
||||
}
|
||||
void WriteMeta(GfoFldList flds, boolean isName, String cmd) {
|
||||
for (int i = 0; i < flds.Count(); i++) {
|
||||
GfoFld fld = flds.Get_at(i);
|
||||
String val = isName ? fld.Key(): fld.Type().Key();
|
||||
sb.WriteFld(val);
|
||||
}
|
||||
if (layout.WriteCmdSequence()) sb.WriteCmd(cmd);
|
||||
sb.WriteRowSep();
|
||||
}
|
||||
void WriteComment(String comment) {
|
||||
sb.WriteFld(comment);
|
||||
sb.WriteCmd(sym.CommentSym());
|
||||
sb.WriteRowSep();
|
||||
}
|
||||
@Override public SrlMgr SrlMgr_new(Object o) {return new DsvDataWtr();}
|
||||
DsvStringBldr sb; DsvSymbols sym = DsvSymbols.default_(); DsvStoreLayout layout = DsvStoreLayout.csv_dat_();
|
||||
@gplx.Internal protected DsvDataWtr() {sb = DsvStringBldr.new_(sym);}
|
||||
}
|
||||
class DsvStringBldr {
|
||||
public void Clear() {sb.Clear();}
|
||||
public String To_str() {return sb.To_str();}
|
||||
public void WriteCmd(String cmd) {
|
||||
WriteFld(sym.CmdSequence(), true);
|
||||
WriteFld(cmd);
|
||||
}
|
||||
public void WriteFldSep() {sb.Add(sym.FldSep());}
|
||||
public void WriteRowSep() {
|
||||
sb.Add(sym.RowSep());
|
||||
isNewRow = true;
|
||||
}
|
||||
public void WriteFld(String val) {WriteFld(val, false);}
|
||||
void WriteFld(String val, boolean writeRaw) {
|
||||
if (isNewRow) // if isNewRow, then fld is first, and no fldSpr needed (RowSep serves as fldSpr)
|
||||
isNewRow = false;
|
||||
else
|
||||
sb.Add(sym.FldSep());
|
||||
|
||||
if (val == null) {} // null -> append nothing
|
||||
else if (String_.Eq(val, String_.Empty))// "" -> append ""
|
||||
sb.Add("\"\"");
|
||||
else if (writeRaw) // only cmds should be writeRaw (will append ," ")
|
||||
sb.Add(val);
|
||||
else { // escape as necessary; ex: "the quote "" char"; "the comma , char"
|
||||
boolean quoteField = false;
|
||||
if (String_.Has(val, sym.QteDlm())) {
|
||||
val = String_.Replace(val, "\"", "\"\"");
|
||||
quoteField = true;
|
||||
}
|
||||
else if (String_.Has(val, sym.FldSep()))
|
||||
quoteField = true;
|
||||
else if (sym.RowSepIsNewLine()
|
||||
&& (String_.Has(val, "\n") || String_.Has(val, "\r")))
|
||||
quoteField = true;
|
||||
else if (String_.Has(val, sym.RowSep()))
|
||||
quoteField = true;
|
||||
|
||||
if (quoteField) sb.Add(sym.QteDlm());
|
||||
sb.Add(val);
|
||||
if (quoteField) sb.Add(sym.QteDlm());
|
||||
}
|
||||
}
|
||||
|
||||
String_bldr sb = String_bldr_.new_(); DsvSymbols sym; boolean isNewRow = true;
|
||||
public static DsvStringBldr new_(DsvSymbols sym) {
|
||||
DsvStringBldr rv = new DsvStringBldr();
|
||||
rv.sym = sym;
|
||||
return rv;
|
||||
} DsvStringBldr() {}
|
||||
}
|
||||
31
100_core/src/gplx/langs/dsvs/DsvDataWtr_.java
Normal file
31
100_core/src/gplx/langs/dsvs/DsvDataWtr_.java
Normal 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.langs.dsvs; import gplx.*; import gplx.langs.*;
|
||||
public class DsvDataWtr_ {
|
||||
public static DsvDataWtr csv_hdr_() {
|
||||
DsvDataWtr rv = new DsvDataWtr();
|
||||
rv.InitWtr(DsvStoreLayout.Key_const, DsvStoreLayout.csv_hdr_());
|
||||
return rv;
|
||||
}
|
||||
public static DsvDataWtr csv_dat_() {
|
||||
DsvDataWtr rv = new DsvDataWtr();
|
||||
rv.InitWtr(DsvStoreLayout.Key_const, DsvStoreLayout.csv_dat_());
|
||||
return rv;
|
||||
}
|
||||
public static DsvDataWtr new_() {return new DsvDataWtr();}
|
||||
}
|
||||
100
100_core/src/gplx/langs/dsvs/DsvDataWtr_csv_tst.java
Normal file
100
100_core/src/gplx/langs/dsvs/DsvDataWtr_csv_tst.java
Normal 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.langs.dsvs; import gplx.*; import gplx.langs.*;
|
||||
import org.junit.*; import gplx.core.gfo_ndes.*; import gplx.core.type_xtns.*;
|
||||
public class DsvDataWtr_csv_tst {
|
||||
@Test public void Dat_Val_0() {
|
||||
root = fx_nde.csv_dat_(); this.AddCsvRow(root);
|
||||
expd = String_.Concat_lines_crlf("");
|
||||
fx.tst_XtoStr(wtr, root, expd);
|
||||
}
|
||||
@Test public void Dat_Val_1() {
|
||||
root = fx_nde.csv_dat_(); this.AddCsvRow(root, "a");
|
||||
expd = String_.Concat_lines_crlf("a");
|
||||
fx.tst_XtoStr(wtr, root, expd);
|
||||
}
|
||||
@Test public void Dat_Val_N() {
|
||||
root = fx_nde.csv_dat_(); this.AddCsvRow(root, "a", "b", "c");
|
||||
expd = String_.Concat_lines_crlf("a,b,c");
|
||||
fx.tst_XtoStr(wtr, root, expd);
|
||||
}
|
||||
@Test public void Dat_Row_N() {
|
||||
root = fx_nde.csv_dat_();
|
||||
this.AddCsvRow(root, "a", "b", "c");
|
||||
this.AddCsvRow(root, "d", "e", "f");
|
||||
expd = String_.Concat_lines_crlf
|
||||
( "a,b,c"
|
||||
, "d,e,f"
|
||||
);
|
||||
fx.tst_XtoStr(wtr, root, expd);
|
||||
}
|
||||
@Test public void Dat_Escape_FldSpr() { // ,
|
||||
root = fx_nde.csv_dat_(); this.AddCsvRow(root, "a", ",", "c");
|
||||
expd = String_.Concat_lines_crlf("a,\",\",c");
|
||||
fx.tst_XtoStr(wtr, root, expd);
|
||||
}
|
||||
@Test public void Dat_Escape_RcdSpr() { // NewLine
|
||||
root = fx_nde.csv_dat_(); this.AddCsvRow(root, "a", String_.CrLf, "c");
|
||||
expd = String_.Concat_lines_crlf("a,\"" + String_.CrLf + "\",c");
|
||||
fx.tst_XtoStr(wtr, root, expd);
|
||||
}
|
||||
@Test public void Dat_Escape_Quote() { // " -> ""
|
||||
root = fx_nde.csv_dat_(); this.AddCsvRow(root, "a", "\"", "c");
|
||||
expd = String_.Concat_lines_crlf("a,\"\"\"\",c");
|
||||
fx.tst_XtoStr(wtr, root, expd);
|
||||
}
|
||||
@Test public void Dat_Whitespace() {
|
||||
root = fx_nde.csv_dat_(); this.AddCsvRow(root, "a", " b\t", "c");
|
||||
expd = String_.Concat_lines_crlf("a, b\t,c");
|
||||
fx.tst_XtoStr(wtr, root, expd);
|
||||
}
|
||||
@Test public void Dat_Null() {
|
||||
root = fx_nde.csv_dat_(); this.AddCsvRow(root, "a", null, "c");
|
||||
expd = String_.Concat_lines_crlf("a,,c");
|
||||
fx.tst_XtoStr(wtr, root, expd);
|
||||
}
|
||||
@Test public void Dat_EmptyString() {
|
||||
root = fx_nde.csv_dat_(); this.AddCsvRow(root, "a", "", "c");
|
||||
expd = String_.Concat_lines_crlf("a,\"\",c");
|
||||
fx.tst_XtoStr(wtr, root, expd);
|
||||
}
|
||||
@Test public void Hdr_Flds() {
|
||||
wtr = DsvDataWtr_.csv_hdr_();
|
||||
GfoFldList flds = GfoFldList_.new_().Add("id", StringClassXtn.Instance).Add("name", StringClassXtn.Instance);
|
||||
root = fx_nde.csv_hdr_(flds); this.AddCsvRow(root, "0", "me");
|
||||
expd = String_.Concat_lines_crlf
|
||||
( "id,name"
|
||||
, "0,me"
|
||||
);
|
||||
fx.tst_XtoStr(wtr, root, expd);
|
||||
}
|
||||
void AddCsvRow(GfoNde root, String... ary) {
|
||||
GfoNde sub = GfoNde_.vals_(root.SubFlds(), ary);
|
||||
root.Subs().Add(sub);
|
||||
}
|
||||
GfoNde root; String expd; DsvDataWtr wtr = DsvDataWtr_.csv_dat_(); DsvDataWtr_fxt fx = DsvDataWtr_fxt.new_(); GfoNdeFxt fx_nde = GfoNdeFxt.new_();
|
||||
}
|
||||
class DsvDataWtr_fxt {
|
||||
public void tst_XtoStr(DsvDataWtr wtr, GfoNde root, String expd) {
|
||||
wtr.Clear();
|
||||
root.XtoStr_wtr(wtr);
|
||||
String actl = wtr.To_str();
|
||||
Tfds.Eq(expd, actl);
|
||||
}
|
||||
public static DsvDataWtr_fxt new_() {return new DsvDataWtr_fxt();} DsvDataWtr_fxt() {}
|
||||
}
|
||||
73
100_core/src/gplx/langs/dsvs/DsvDataWtr_tbls_tst.java
Normal file
73
100_core/src/gplx/langs/dsvs/DsvDataWtr_tbls_tst.java
Normal 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.langs.dsvs; import gplx.*; import gplx.langs.*;
|
||||
import org.junit.*; import gplx.core.gfo_ndes.*;
|
||||
public class DsvDataWtr_tbls_tst {
|
||||
@Before public void setup() {
|
||||
DsvStoreLayout layout = DsvStoreLayout.dsv_brief_();
|
||||
layout.HeaderList().Add_TableName();
|
||||
wtr.InitWtr(DsvStoreLayout.Key_const, layout);
|
||||
}
|
||||
@Test public void Rows_0() {
|
||||
root = fx_nde.tbl_("tbl0");
|
||||
expd = String_.Concat_lines_crlf( "tbl0, ,\" \",#");
|
||||
fx.tst_XtoStr(wtr, root, expd);
|
||||
}
|
||||
@Test public void Rows_N() {
|
||||
root = fx_nde.tbl_
|
||||
( "numbers"
|
||||
, fx_nde.row_vals_(1, 2, 3)
|
||||
, fx_nde.row_vals_(4, 5, 6)
|
||||
);
|
||||
expd = String_.Concat_lines_crlf
|
||||
( "numbers, ,\" \",#"
|
||||
, "1,2,3"
|
||||
, "4,5,6"
|
||||
);
|
||||
fx.tst_XtoStr(wtr, root, expd);
|
||||
}
|
||||
@Test public void Tbls_N_Empty() {
|
||||
root = fx_nde.root_
|
||||
( fx_nde.tbl_("tbl0")
|
||||
, fx_nde.tbl_("tbl1")
|
||||
);
|
||||
expd = String_.Concat_lines_crlf
|
||||
( "tbl0, ,\" \",#"
|
||||
, "tbl1, ,\" \",#"
|
||||
);
|
||||
fx.tst_XtoStr(wtr, root, expd);
|
||||
}
|
||||
@Test public void Tbls_N() {
|
||||
root = fx_nde.root_
|
||||
( fx_nde.tbl_("letters"
|
||||
, fx_nde.row_vals_("a", "b", "c"))
|
||||
, fx_nde.tbl_("numbers"
|
||||
, fx_nde.row_vals_(1, 2, 3)
|
||||
, fx_nde.row_vals_(4, 5, 6)
|
||||
));
|
||||
expd = String_.Concat_lines_crlf
|
||||
( "letters, ,\" \",#"
|
||||
, "a,b,c"
|
||||
, "numbers, ,\" \",#"
|
||||
, "1,2,3"
|
||||
, "4,5,6"
|
||||
);
|
||||
fx.tst_XtoStr(wtr, root, expd);
|
||||
}
|
||||
GfoNde root; String expd; DsvDataWtr wtr = DsvDataWtr_.csv_dat_(); DsvDataWtr_fxt fx = DsvDataWtr_fxt.new_(); GfoNdeFxt fx_nde = GfoNdeFxt.new_();
|
||||
}
|
||||
44
100_core/src/gplx/langs/dsvs/DsvHeaderList.java
Normal file
44
100_core/src/gplx/langs/dsvs/DsvHeaderList.java
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.langs.dsvs; import gplx.*; import gplx.langs.*;
|
||||
public class DsvHeaderList {
|
||||
@gplx.Internal protected int Count() {return list.Count();}
|
||||
@gplx.Internal protected DsvHeaderItm Get_at(int i) {return (DsvHeaderItm)list.Get_at(i);}
|
||||
public DsvHeaderList Add_LeafTypes() {this.Add(new DsvHeaderItm(DsvHeaderItm.Id_LeafTypes, null)); return this;}
|
||||
public DsvHeaderList Add_LeafNames() {this.Add(new DsvHeaderItm(DsvHeaderItm.Id_LeafNames, null)); return this;}
|
||||
public DsvHeaderList Add_TableName() {this.Add(new DsvHeaderItm(DsvHeaderItm.Id_TableName, null)); return this;}
|
||||
public DsvHeaderList Add_BlankLine() {this.Add(new DsvHeaderItm(DsvHeaderItm.Id_BlankLine, null)); return this;}
|
||||
public DsvHeaderList Add_Comment(String comment) {this.Add(new DsvHeaderItm(DsvHeaderItm.Id_Comment, comment)); return this;}
|
||||
void Add(DsvHeaderItm data) {list.Add(data);}
|
||||
|
||||
List_adp list = List_adp_.New();
|
||||
public static DsvHeaderList new_() {return new DsvHeaderList();} DsvHeaderList() {}
|
||||
}
|
||||
class DsvHeaderItm {
|
||||
public int Id() {return id;} int id;
|
||||
public Object Val() {return val;} Object val;
|
||||
@gplx.Internal protected DsvHeaderItm(int id, Object val) {this.id = id; this.val = val;}
|
||||
|
||||
public static final int
|
||||
Id_Comment = 1
|
||||
, Id_TableName = 2
|
||||
, Id_BlankLine = 3
|
||||
, Id_LeafTypes = 4
|
||||
, Id_LeafNames = 5
|
||||
;
|
||||
}
|
||||
51
100_core/src/gplx/langs/dsvs/DsvStoreLayout.java
Normal file
51
100_core/src/gplx/langs/dsvs/DsvStoreLayout.java
Normal 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.langs.dsvs; import gplx.*; import gplx.langs.*;
|
||||
public class DsvStoreLayout {
|
||||
public DsvHeaderList HeaderList() {return headerList;} DsvHeaderList headerList = DsvHeaderList.new_();
|
||||
@gplx.Internal protected boolean WriteCmdSequence() {return writeCmdSequence;} @gplx.Internal protected DsvStoreLayout WriteCmdSequence_(boolean val) {writeCmdSequence = val; return this;} private boolean writeCmdSequence;
|
||||
|
||||
static DsvStoreLayout new_() {return new DsvStoreLayout();}
|
||||
public static DsvStoreLayout csv_dat_() {return new_();}
|
||||
public static DsvStoreLayout csv_hdr_() {
|
||||
DsvStoreLayout rv = new_();
|
||||
rv.HeaderList().Add_LeafNames();
|
||||
return rv;
|
||||
}
|
||||
public static DsvStoreLayout dsv_brief_() {
|
||||
DsvStoreLayout rv = new_();
|
||||
rv.writeCmdSequence = true;
|
||||
return rv;
|
||||
}
|
||||
public static DsvStoreLayout dsv_full_() {
|
||||
DsvStoreLayout rv = DsvStoreLayout.new_();
|
||||
rv.writeCmdSequence = true;
|
||||
rv.HeaderList().Add_BlankLine();
|
||||
rv.HeaderList().Add_BlankLine();
|
||||
rv.HeaderList().Add_Comment("================================");
|
||||
rv.HeaderList().Add_TableName();
|
||||
rv.HeaderList().Add_Comment("================================");
|
||||
rv.HeaderList().Add_LeafTypes();
|
||||
rv.HeaderList().Add_LeafNames();
|
||||
rv.HeaderList().Add_Comment("================================");
|
||||
return rv;
|
||||
}
|
||||
public static DsvStoreLayout as_(Object obj) {return obj instanceof DsvStoreLayout ? (DsvStoreLayout)obj : null;}
|
||||
public static DsvStoreLayout cast(Object obj) {try {return (DsvStoreLayout)obj;} catch(Exception exc) {throw Err_.new_type_mismatch_w_exc(exc, DsvStoreLayout.class, obj);}}
|
||||
public static final String Key_const = "StoreLayoutWtr";
|
||||
}
|
||||
52
100_core/src/gplx/langs/dsvs/DsvSymbols.java
Normal file
52
100_core/src/gplx/langs/dsvs/DsvSymbols.java
Normal 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.langs.dsvs; import gplx.*; import gplx.langs.*;
|
||||
class DsvSymbols {
|
||||
public String FldSep() {return fldSep;} public DsvSymbols FldSep_(String v) {fldSep = v; CmdSequence_set(); return this;} private String fldSep;
|
||||
public String RowSep() {return rowSep;}
|
||||
public DsvSymbols RowSep_(String v) {
|
||||
rowSep = v;
|
||||
rowSepIsNewLine = String_.Has(v, "\n") || String_.Has(v, "\r");
|
||||
return this;
|
||||
} String rowSep;
|
||||
public String QteDlm() {return qteDlm;} public void QteDlm_set(String v) {qteDlm = v; CmdSequence_set();} private String qteDlm;
|
||||
public String CmdDlm() {return cmdDlm;} public void CmdDlm_set(String v) {cmdDlm = v; CmdSequence_set();} private String cmdDlm;
|
||||
public String CmdSequence() {return cmdSequence;} private String cmdSequence;
|
||||
public String CommentSym() {return commentSym;} public void CommentSym_set(String v) {commentSym = v;} private String commentSym;
|
||||
public String TblNameSym() {return tblNameSym;} public void TblNamesSym_set(String v) {tblNameSym = v;} private String tblNameSym;
|
||||
public String FldNamesSym() {return fldNamesSym;} public void FldNamesSym_set(String v) {fldNamesSym = v;} private String fldNamesSym;
|
||||
public String FldTypesSym() {return fldTypesSym;} public void FldTypesSym_set(String v) {fldTypesSym = v;} private String fldTypesSym;
|
||||
public boolean RowSepIsNewLine() {return rowSepIsNewLine;} private boolean rowSepIsNewLine;
|
||||
public void Reset() {
|
||||
fldSep = ",";
|
||||
RowSep_ ("\r\n");
|
||||
|
||||
qteDlm = "\"";
|
||||
cmdDlm = " ";
|
||||
CmdSequence_set();
|
||||
|
||||
commentSym = "//";
|
||||
tblNameSym = "#";
|
||||
fldNamesSym = "@";
|
||||
fldTypesSym = "$";
|
||||
}
|
||||
void CmdSequence_set() { // commandDelimiters are repeated; once without quotes and once with quotes; ex: , ," ",
|
||||
cmdSequence = String_.Concat(cmdDlm, fldSep, qteDlm, cmdDlm, qteDlm);
|
||||
}
|
||||
public static DsvSymbols default_() {return new DsvSymbols();} DsvSymbols() {this.Reset();}
|
||||
}
|
||||
90
100_core/src/gplx/langs/gfs/GfsCore.java
Normal file
90
100_core/src/gplx/langs/gfs/GfsCore.java
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
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.langs.gfs; import gplx.*; import gplx.langs.*;
|
||||
import gplx.core.gfo_regys.*;
|
||||
public class GfsCore implements Gfo_invk {
|
||||
public Gfo_invk Root() {return root;}
|
||||
@gplx.Internal protected GfsRegy Root_as_regy() {return root;} GfsRegy root = GfsRegy.new_();
|
||||
public void Clear() {root.Clear();}
|
||||
public GfoMsgParser MsgParser() {return msgParser;} public GfsCore MsgParser_(GfoMsgParser v) {msgParser = v; return this;} GfoMsgParser msgParser;
|
||||
public void Del(String key) {root.Del(key);}
|
||||
public void AddLib(GfsLibIni... ary) {for (GfsLibIni itm : ary) itm.Ini(this);}
|
||||
public void AddCmd(Gfo_invk invk, String key) {root.AddCmd(invk, key);}
|
||||
public void AddObj(Gfo_invk invk, String key) {root.AddObj(invk, key);}
|
||||
public void AddDeep(Gfo_invk invk, String... ary) {
|
||||
Gfo_invk_cmd_mgr_owner cur = (Gfo_invk_cmd_mgr_owner)((GfsRegyItm)root.Get_by(ary[0])).InvkAble();
|
||||
for (int i = 1; i < ary.length - 1; i++)
|
||||
cur = (Gfo_invk_cmd_mgr_owner)cur.InvkMgr().Invk(GfsCtx.Instance, 0, ary[i], GfoMsg_.Null, cur);
|
||||
cur.InvkMgr().Add_cmd(ary[ary.length - 1], invk);
|
||||
}
|
||||
public String FetchKey(Gfo_invk invk) {return root.FetchByType(invk).Key();}
|
||||
public Object ExecOne(GfsCtx ctx, GfoMsg msg) {return GfsCore_.Exec(ctx, root, msg, null, 0);}
|
||||
public Object ExecOne_to(GfsCtx ctx, Gfo_invk invk, GfoMsg msg) {return GfsCore_.Exec(ctx, invk, msg, null, 0);}
|
||||
public Object ExecMany(GfsCtx ctx, GfoMsg rootMsg) {
|
||||
Object rv = null;
|
||||
for (int i = 0; i < rootMsg.Subs_count(); i++) {
|
||||
GfoMsg subMsg = (GfoMsg)rootMsg.Subs_getAt(i);
|
||||
rv = GfsCore_.Exec(ctx, root, subMsg, null, 0);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public void ExecRegy(String key) {
|
||||
GfoRegyItm itm = GfoRegy.Instance.FetchOrNull(key);
|
||||
if (itm == null) {UsrDlg_.Instance.Warn(UsrMsg.new_("could not find script for key").Add("key", key)); return;}
|
||||
Io_url url = itm.Url();
|
||||
if (!Io_mgr.Instance.ExistsFil(url)) {
|
||||
UsrDlg_.Instance.Warn(UsrMsg.new_("script url does not exist").Add("key", key).Add("url", url));
|
||||
return;
|
||||
}
|
||||
this.ExecText(Io_mgr.Instance.LoadFilStr(url));
|
||||
}
|
||||
public Object ExecFile_ignoreMissing(Io_url url) {if (!Io_mgr.Instance.ExistsFil(url)) return null; return ExecText(Io_mgr.Instance.LoadFilStr(url));}
|
||||
public Object ExecFile(Io_url url) {return ExecText(Io_mgr.Instance.LoadFilStr(url));}
|
||||
public Object ExecFile_ignoreMissing(Gfo_invk root, Io_url url) {
|
||||
if (!Io_mgr.Instance.ExistsFil(url)) return null;
|
||||
if (msgParser == null) throw Err_.new_wo_type("msgParser is null");
|
||||
return Exec_bry(Io_mgr.Instance.LoadFilBry(url), root);
|
||||
}
|
||||
public Object Exec_bry(byte[] bry) {return Exec_bry(bry, root);}
|
||||
public Object Exec_bry(byte[] bry, Gfo_invk root) {
|
||||
GfoMsg rootMsg = msgParser.ParseToMsg(String_.new_u8(bry));
|
||||
Object rv = null;
|
||||
GfsCtx ctx = GfsCtx.new_();
|
||||
for (int i = 0; i < rootMsg.Subs_count(); i++) {
|
||||
GfoMsg subMsg = (GfoMsg)rootMsg.Subs_getAt(i);
|
||||
rv = GfsCore_.Exec(ctx, root, subMsg, null, 0);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public Object ExecText(String text) {
|
||||
if (msgParser == null) throw Err_.new_wo_type("msgParser is null");
|
||||
GfsCtx ctx = GfsCtx.new_();
|
||||
return ExecMany(ctx, msgParser.ParseToMsg(text));
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_ExecFil)) {
|
||||
Io_url url = m.ReadIoUrl("url");
|
||||
if (ctx.Deny()) return this;
|
||||
return ExecFile(url);
|
||||
}
|
||||
else return Gfo_invk_.Rv_unhandled;
|
||||
// return this;
|
||||
} public static final String Invk_ExecFil = "ExecFil";
|
||||
public static final GfsCore Instance = new GfsCore();
|
||||
@gplx.Internal protected static GfsCore new_() {return new GfsCore();}
|
||||
}
|
||||
73
100_core/src/gplx/langs/gfs/GfsCoreHelp.java
Normal file
73
100_core/src/gplx/langs/gfs/GfsCoreHelp.java
Normal 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.langs.gfs; import gplx.*; import gplx.langs.*;
|
||||
import gplx.core.strings.*;
|
||||
class GfsCoreHelp implements Gfo_invk {
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
String path = m.ReadStrOr("path", "");
|
||||
if (String_.Eq(path, "")) {
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
for (int i = 0; i < core.Root_as_regy().Count(); i++) {
|
||||
GfsRegyItm itm = (GfsRegyItm)core.Root_as_regy().Get_at(i);
|
||||
sb.Add_spr_unless_first(itm.Key(), String_.CrLf, i);
|
||||
}
|
||||
return sb.To_str();
|
||||
}
|
||||
else return Exec(ctx, core.Root_as_regy(), path);
|
||||
}
|
||||
public static Err Err_Unhandled(String objPath, String key) {return Err_.new_wo_type("obj does not handle msgKey", "objPath", objPath, "key", key).Trace_ignore_add_1_();}
|
||||
static Err Err_Unhandled(String[] itmAry, int i) {
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
for (int j = 0; j < i; j++)
|
||||
sb.Add_spr_unless_first(itmAry[j], ".", j);
|
||||
return Err_Unhandled(sb.To_str(), itmAry[i]);
|
||||
}
|
||||
static Object Exec(GfsCtx rootCtx, Gfo_invk rootInvk, String path) {
|
||||
String[] itmAry = String_.Split(path, ".");
|
||||
Gfo_invk invk = rootInvk;
|
||||
GfsCtx ctx = GfsCtx.new_();
|
||||
Object curRv = null;
|
||||
for (int i = 0; i < itmAry.length; i++) {
|
||||
String itm = itmAry[i];
|
||||
curRv = invk.Invk(ctx, 0, itm, GfoMsg_.Null);
|
||||
if (curRv == Gfo_invk_.Rv_unhandled) throw Err_Unhandled(itmAry, i);
|
||||
invk = (Gfo_invk)curRv;
|
||||
}
|
||||
GfsCoreHelp helpData = GfsCoreHelp.as_(curRv);
|
||||
if (helpData != null) { // last itm is actually Method
|
||||
return "";
|
||||
}
|
||||
else {
|
||||
ctx = GfsCtx.new_().Help_browseMode_(true);
|
||||
invk.Invk(ctx, 0, "", GfoMsg_.Null);
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
for (int i = 0; i < ctx.Help_browseList().Count(); i++) {
|
||||
String s = (String)ctx.Help_browseList().Get_at(i);
|
||||
sb.Add_spr_unless_first(s, String_.CrLf, i);
|
||||
}
|
||||
return sb.To_str();
|
||||
}
|
||||
}
|
||||
public static GfsCoreHelp as_(Object obj) {return obj instanceof GfsCoreHelp ? (GfsCoreHelp)obj : null;}
|
||||
public static GfsCoreHelp new_(GfsCore core) {
|
||||
GfsCoreHelp rv = new GfsCoreHelp();
|
||||
rv.core = core;
|
||||
return rv;
|
||||
} GfsCoreHelp() {}
|
||||
GfsCore core;
|
||||
}
|
||||
96
100_core/src/gplx/langs/gfs/GfsCore_.java
Normal file
96
100_core/src/gplx/langs/gfs/GfsCore_.java
Normal 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.langs.gfs; import gplx.*; import gplx.langs.*;
|
||||
public class GfsCore_ {
|
||||
public static final String Arg_primitive = "v";
|
||||
public static Object Exec(GfsCtx ctx, Gfo_invk owner_invk, GfoMsg owner_msg, Object owner_primitive, int depth) {
|
||||
if (owner_msg.Args_count() == 0 && owner_msg.Subs_count() == 0 && String_.Eq(owner_msg.Key(), "")) {UsrDlg_.Instance.Warn("empty msg"); return Gfo_invk_.Rv_unhandled;}
|
||||
if (owner_primitive != null) owner_msg.Parse_(false).Add(GfsCore_.Arg_primitive, owner_primitive);
|
||||
Object rv = owner_invk.Invk(ctx, 0, owner_msg.Key(), owner_msg);
|
||||
if (rv == Gfo_invk_.Rv_cancel) return rv;
|
||||
else if (rv == Gfo_invk_.Rv_unhandled) {
|
||||
if (ctx.Fail_if_unhandled())
|
||||
throw Err_.new_wo_type("Object does not support key", "key", owner_msg.Key(), "ownerType", Type_adp_.FullNameOf_obj(owner_invk));
|
||||
else {
|
||||
Gfo_usr_dlg usr_dlg = ctx.Usr_dlg();
|
||||
if (usr_dlg != null) usr_dlg.Warn_many(GRP_KEY, "unhandled_key", "Object does not support key: key=~{0} ownerType=~{1}", owner_msg.Key(), Type_adp_.FullNameOf_obj(owner_invk));
|
||||
return Gfo_invk_.Noop;
|
||||
}
|
||||
}
|
||||
if (owner_msg.Subs_count() == 0) { // msg is leaf
|
||||
GfsRegyItm regyItm = GfsRegyItm.as_(rv);
|
||||
if (regyItm == null) return rv; // rv is primitive or other non-regy Object
|
||||
if (regyItm.IsCmd()) // rv is cmd; invk cmd
|
||||
return regyItm.InvkAble().Invk(ctx, 0, owner_msg.Key(), owner_msg);
|
||||
else // rv is host
|
||||
return regyItm.InvkAble();
|
||||
}
|
||||
else { // intermediate; cast to invk and call Exec
|
||||
Gfo_invk invk = Gfo_invk_.as_(rv);
|
||||
Object primitive = null;
|
||||
if (invk == null) { // rv is primitive; find appropriate mgr
|
||||
Class<?> type = rv.getClass();
|
||||
if (type == String.class) invk = String_.Gfs;
|
||||
else if (Int_.TypeMatch(type)) invk = Int_.Gfs;
|
||||
else if (Type_adp_.Eq(type, Bool_.Cls_ref_type)) invk = Bool_.Gfs;
|
||||
else throw Err_.new_wo_type("unknown primitive", "type", Type_adp_.NameOf_type(type), "obj", Object_.Xto_str_strict_or_null_mark(rv));
|
||||
primitive = rv;
|
||||
}
|
||||
Object exec_rv = null;
|
||||
int len = owner_msg.Subs_count();
|
||||
for (int i = 0; i < len; i++) // iterate over subs; needed for a{b;c;d;}
|
||||
exec_rv = Exec(ctx, invk, owner_msg.Subs_getAt(i), primitive, depth + 1);
|
||||
return exec_rv;
|
||||
}
|
||||
}
|
||||
static final String GRP_KEY = "gplx.gfs_core";
|
||||
}
|
||||
// class GfsRegyMgr : Gfo_invk {
|
||||
// public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
// if (ctx.Match(k, Invk_Add)) {
|
||||
// String libKey = m.ReadStr("libKey"), regKey = m.ReadStr("regKey");
|
||||
// if (ctx.Deny()) return this;
|
||||
// GfsRegyItm itm = regy.Get_by(libKey);
|
||||
// if (regy.Has(regKey)) {ctx.Write_warn("'{0}' already exists", regKey); return this;}
|
||||
// regy.Add(regKey, itm.InvkAble(), itm.Type_cmd());
|
||||
// ctx.Write_note("added '{0}' as '{1}'", regKey, libKey);
|
||||
// }
|
||||
// else if (ctx.Match(k, Invk_Del)) {
|
||||
// String regKey = m.ReadStr("regKey");
|
||||
// if (ctx.Deny()) return this;
|
||||
// if (!regy.Has(regKey)) {ctx.Write_warn("{0} does not exist", regKey); return this;}
|
||||
// regy.Del(regKey);
|
||||
// ctx.Write_note("removed '{0}'", regKey);
|
||||
// }
|
||||
// else if (ctx.Match(k, Invk_Load)) {
|
||||
// Io_url url = (Io_url)m.ReadObj("url", Io_url_.Parser);
|
||||
// if (ctx.Deny()) return this;
|
||||
// String loadText = Io_mgr.Instance.LoadFilStr(url);
|
||||
// GfoMsg loadMsg = core.MsgParser().ParseToMsg(loadText);
|
||||
// return core.Exec(ctx, loadMsg);
|
||||
// }
|
||||
// else return Gfo_invk_.Rv_unhandled;
|
||||
// return this;
|
||||
// } public static final String Invk_Add = "Add", Invk_Del = "Del", Invk_Load = "Load";
|
||||
// GfsCore core; GfsRegy regy;
|
||||
// public static GfsRegyMgr new_(GfsCore core, GfsRegy regy) {
|
||||
// GfsRegyMgr rv = new GfsRegyMgr();
|
||||
// rv.core = core; rv.regy = regy;
|
||||
// return rv;
|
||||
// } GfsRegyMgr() {}
|
||||
// }
|
||||
113
100_core/src/gplx/langs/gfs/GfsCore_tst.java
Normal file
113
100_core/src/gplx/langs/gfs/GfsCore_tst.java
Normal 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.langs.gfs; import gplx.*; import gplx.langs.*;
|
||||
import org.junit.*;
|
||||
public class GfsCore_tst {
|
||||
@Before public void setup() {
|
||||
core = GfsCore.new_();
|
||||
core.AddObj(String_.Gfs, "String_");
|
||||
core.AddObj(Int_.Gfs, "Int_");
|
||||
} GfsCore core;
|
||||
@Test public void Basic() { // String_.Len('abc') >> 3
|
||||
tst_Msg
|
||||
( msg_("String_").Subs_
|
||||
( msg_("Len").Add("v", "abc"))
|
||||
, 3);
|
||||
}
|
||||
@Test public void PrimitiveConversion() { // String_.Len('abc').Add(-3) >> 0
|
||||
tst_Msg
|
||||
( msg_("String_").Subs_
|
||||
( msg_("Len").Add("v", "abc").Subs_
|
||||
( msg_("Add").Add("operand", -3))
|
||||
)
|
||||
, 0);
|
||||
}
|
||||
// @Test public void Fail_notFound() { // String_.DoesNotExists
|
||||
// tst_Err
|
||||
// ( msg_("help").Add("", "String_.DoesNotExist")
|
||||
// , GfsHelp.Err_Unhandled("String_", "DoesNotExist"));
|
||||
// }
|
||||
@Test public void Cmd() { // cmd
|
||||
core.AddCmd(new GfsTest_cmd(), "testCmd");
|
||||
tst_Msg
|
||||
( msg_("testCmd").Add("s", "pass")
|
||||
, "pass");
|
||||
}
|
||||
@Test public void EmptyMsg() {
|
||||
tst_Msg
|
||||
( msg_("")
|
||||
, Gfo_invk_.Rv_unhandled);
|
||||
}
|
||||
// @Test public void Fail_argMissing() { // String_.Len()
|
||||
// tst_String__Len_Err(msg_("Len"), GfsCtx.Err_KeyNotFound("v", "<<EMPTY>>"));
|
||||
// }
|
||||
// @Test public void Fail_argWrongKey() { // String_.Len(badKey='abc')
|
||||
// tst_String__Len_Err(msg_("Len").Add("badKey", "abc"), GfsCtx.Err_KeyNotFound("v", "badKey;"));
|
||||
// }
|
||||
// @Test public void Fail_argExtraKey() { // String_.Len(v='abc' extraKey=1)
|
||||
// tst_String__Len_Err(msg_("Len").Add("v", "abc").Add("extraKey", 1), GfsCtx.Err_KeyNotFound("v", "badKey;"));
|
||||
// }
|
||||
@Test public void Add_obj_deep() { // String_.Len(badKey='abc')
|
||||
GfsCore_tst_nest obj1 = GfsCore_tst_nest.new_("1", "val1");
|
||||
GfsCore_tst_nest obj1_1 = GfsCore_tst_nest.new_("1_1", "val2");
|
||||
core.AddObj(obj1, "1");
|
||||
core.AddDeep(obj1_1, "1", "1_1");
|
||||
|
||||
GfoMsg root = GfoMsg_.root_("1", "1_1", GfsCore_tst_nest.Prop2);
|
||||
Object actl = core.ExecOne(GfsCtx.Instance, root);
|
||||
Tfds.Eq("val2", actl);
|
||||
}
|
||||
void tst_String__Len_Err(GfoMsg m, Err expd) {
|
||||
tst_Err(msg_("String_").Subs_(m), expd);
|
||||
}
|
||||
void tst_Err(GfoMsg msg, Err expd) {
|
||||
GfoMsg root = msg;
|
||||
GfsCtx ctx = GfsCtx.new_();
|
||||
try {
|
||||
core.ExecOne(ctx, root);
|
||||
Tfds.Fail_expdError();
|
||||
}
|
||||
catch (Exception e) {
|
||||
Tfds.Eq_err(expd, e);
|
||||
}
|
||||
}
|
||||
GfoMsg msg_(String k) {return GfoMsg_.new_cast_(k);}
|
||||
void tst_Msg(GfoMsg msg, Object expd) {
|
||||
GfsCtx ctx = GfsCtx.new_();
|
||||
Object actl = core.ExecOne(ctx, msg);
|
||||
Tfds.Eq(expd, actl);
|
||||
}
|
||||
}
|
||||
class GfsCore_tst_nest implements Gfo_invk, Gfo_invk_cmd_mgr_owner {
|
||||
public Gfo_invk_cmd_mgr InvkMgr() {return invkMgr;} Gfo_invk_cmd_mgr invkMgr = Gfo_invk_cmd_mgr.new_();
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Prop1)) {return prop1;}
|
||||
else if (ctx.Match(k, Prop2)) {return prop2;}
|
||||
else if (ctx.Match(k, prop1)) {return this;}
|
||||
else return invkMgr.Invk(ctx, ikey, k, m, this);
|
||||
} public static final String Prop1 = "Prop1", Prop2 = "Prop2";
|
||||
String prop1, prop2;
|
||||
public static GfsCore_tst_nest new_(String prop1, String prop2) {
|
||||
GfsCore_tst_nest rv = new GfsCore_tst_nest();
|
||||
rv.prop1 = prop1; rv.prop2 = prop2;
|
||||
return rv;
|
||||
} GfsCore_tst_nest() {}
|
||||
}
|
||||
class GfsTest_cmd implements Gfo_invk {
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {return m.ReadStr("s");}
|
||||
}
|
||||
21
100_core/src/gplx/langs/gfs/GfsLibIni.java
Normal file
21
100_core/src/gplx/langs/gfs/GfsLibIni.java
Normal 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.langs.gfs; import gplx.*; import gplx.langs.*;
|
||||
public interface GfsLibIni {
|
||||
void Ini(GfsCore core);
|
||||
}
|
||||
36
100_core/src/gplx/langs/gfs/GfsLibIni_core.java
Normal file
36
100_core/src/gplx/langs/gfs/GfsLibIni_core.java
Normal 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.langs.gfs; import gplx.*; import gplx.langs.*;
|
||||
import gplx.core.gfo_regys.*;
|
||||
public class GfsLibIni_core implements GfsLibIni {
|
||||
public void Ini(GfsCore core) {
|
||||
core.AddCmd(GfsCoreHelp.new_(core), "help");
|
||||
core.AddObj(String_.Gfs, "String_");
|
||||
core.AddObj(Int_.Gfs, "Int_");
|
||||
core.AddObj(DateAdp_.Gfs, "Date_");
|
||||
core.AddObj(RandomAdp_.Gfs, "RandomAdp_");
|
||||
core.AddObj(GfoTemplateFactory.Instance, "factory");
|
||||
core.AddObj(GfoRegy.Instance, "GfoRegy_");
|
||||
core.AddObj(GfsCore.Instance, "GfsCore_");
|
||||
core.AddObj(gplx.core.ios.IoUrlInfoRegy.Instance, "IoUrlInfoRegy_");
|
||||
core.AddObj(gplx.core.ios.IoUrlTypeRegy.Instance, "IoUrlTypeRegy_");
|
||||
|
||||
GfoRegy.Instance.Parsers().Add("Io_url", Io_url_.Parser);
|
||||
}
|
||||
public static final GfsLibIni_core Instance = new GfsLibIni_core(); GfsLibIni_core() {}
|
||||
}
|
||||
54
100_core/src/gplx/langs/gfs/GfsRegy.java
Normal file
54
100_core/src/gplx/langs/gfs/GfsRegy.java
Normal 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.langs.gfs; import gplx.*; import gplx.langs.*;
|
||||
class GfsRegy implements Gfo_invk {
|
||||
public int Count() {return hash.Count();}
|
||||
public void Clear() {hash.Clear(); typeHash.Clear();}
|
||||
public boolean Has(String k) {return hash.Has(k);}
|
||||
public GfsRegyItm Get_at(int i) {return (GfsRegyItm)hash.Get_at(i);}
|
||||
public GfsRegyItm Get_by(String key) {return (GfsRegyItm)hash.Get_by(key);}
|
||||
public GfsRegyItm FetchByType(Gfo_invk invk) {return (GfsRegyItm)typeHash.Get_by(Type_adp_.FullNameOf_obj(invk));}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
Object rv = (GfsRegyItm)hash.Get_by(k); if (rv == null) throw Err_.new_missing_key(k);
|
||||
return rv;
|
||||
}
|
||||
public void AddObj(Gfo_invk invk, String key) {Add(key, invk, false);}
|
||||
public void AddCmd(Gfo_invk invk, String key) {Add(key, invk, true);}
|
||||
public void Add(String key, Gfo_invk invk, boolean typeCmd) {
|
||||
if (hash.Has(key)) return;
|
||||
GfsRegyItm regyItm = new GfsRegyItm().Key_(key).InvkAble_(invk).IsCmd_(typeCmd).TypeKey_(Type_adp_.FullNameOf_obj(invk));
|
||||
hash.Add(key, regyItm);
|
||||
typeHash.Add_if_dupe_use_1st(regyItm.TypeKey(), regyItm); // NOTE: changed to allow same Object to be added under different aliases (app, xowa) DATE:2014-06-09;
|
||||
}
|
||||
public void Del(String k) {
|
||||
GfsRegyItm itm =(GfsRegyItm)hash.Get_by(k);
|
||||
if (itm != null) typeHash.Del(itm.TypeKey());
|
||||
hash.Del(k);
|
||||
}
|
||||
Hash_adp typeHash = Hash_adp_.New();
|
||||
Ordered_hash hash = Ordered_hash_.New();
|
||||
public static GfsRegy new_() {return new GfsRegy();} GfsRegy() {}
|
||||
}
|
||||
class GfsRegyItm implements Gfo_invk {
|
||||
public String Key() {return key;} public GfsRegyItm Key_(String v) {key = v; return this;} private String key;
|
||||
public String TypeKey() {return typeKey;} public GfsRegyItm TypeKey_(String v) {typeKey = v; return this;} private String typeKey;
|
||||
public boolean IsCmd() {return isCmd;} public GfsRegyItm IsCmd_(boolean v) {isCmd = v; return this;} private boolean isCmd;
|
||||
public Gfo_invk InvkAble() {return invkAble;} public GfsRegyItm InvkAble_(Gfo_invk v) {invkAble = v; return this;} Gfo_invk invkAble;
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {return invkAble.Invk(ctx, ikey, k, m);}
|
||||
public static GfsRegyItm as_(Object obj) {return obj instanceof GfsRegyItm ? (GfsRegyItm)obj : null;}
|
||||
}
|
||||
28
100_core/src/gplx/langs/gfs/GfsTypeNames.java
Normal file
28
100_core/src/gplx/langs/gfs/GfsTypeNames.java
Normal 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.langs.gfs; import gplx.*; import gplx.langs.*;
|
||||
public class GfsTypeNames {
|
||||
public static final String
|
||||
String = "string"
|
||||
, Int = "int"
|
||||
, Bool = "bool"
|
||||
, Float = "float"
|
||||
, YesNo = "yn"
|
||||
, Date = "date"
|
||||
;
|
||||
}
|
||||
42
100_core/src/gplx/langs/gfs/Gfs_Date_tst.java
Normal file
42
100_core/src/gplx/langs/gfs/Gfs_Date_tst.java
Normal 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.langs.gfs; import gplx.*; import gplx.langs.*;
|
||||
import org.junit.*;
|
||||
public class Gfs_Date_tst {
|
||||
@Before public void setup() {
|
||||
fx = new GfsCoreFxt();
|
||||
fx.AddObj(DateAdp_.Gfs, "Date_");
|
||||
Datetime_now.Manual_y_();
|
||||
} GfsCoreFxt fx;
|
||||
@Test public void Now() {
|
||||
fx.tst_MsgStr(fx.msg_(String_.Ary("Date_", "Now")), DateAdp_.parse_gplx("2001-01-01 00:00:00.000"));
|
||||
}
|
||||
@Test public void Add_day() {
|
||||
fx.tst_MsgStr(fx.msg_(String_.Ary("Date_", "Now", "Add_day"), Keyval_.new_("days", 1)), DateAdp_.parse_gplx("2001-01-02 00:00:00.000"));
|
||||
}
|
||||
}
|
||||
class GfsCoreFxt {
|
||||
public GfsCore Core() {return core;} GfsCore core = GfsCore.new_();
|
||||
public GfoMsg msg_(String[] ary, Keyval... kvAry) {return GfoMsg_.root_leafArgs_(ary, kvAry);}
|
||||
public void AddObj(Gfo_invk invk, String s) {core.AddObj(invk, s);}
|
||||
public void tst_MsgStr(GfoMsg msg, Object expd) {
|
||||
GfsCtx ctx = GfsCtx.new_();
|
||||
Object actl = core.ExecOne(ctx, msg);
|
||||
Tfds.Eq(Object_.Xto_str_strict_or_null_mark(expd), Object_.Xto_str_strict_or_null_mark(actl));
|
||||
}
|
||||
}
|
||||
22
100_core/src/gplx/langs/htmls/Url_encoder_interface.java
Normal file
22
100_core/src/gplx/langs/htmls/Url_encoder_interface.java
Normal 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.langs.htmls; import gplx.*; import gplx.langs.*;
|
||||
public interface Url_encoder_interface {
|
||||
String Encode_str(String v);
|
||||
byte[] Encode_bry(String v);
|
||||
}
|
||||
@@ -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.langs.htmls; import gplx.*; import gplx.langs.*;
|
||||
public class Url_encoder_interface_same implements Url_encoder_interface {
|
||||
public String Encode_str(String v) {return v;}
|
||||
public byte[] Encode_bry(String v) {return Bry_.new_u8(v);}
|
||||
public static final Url_encoder_interface_same Instance = new Url_encoder_interface_same(); Url_encoder_interface_same() {}
|
||||
}
|
||||
35
100_core/src/gplx/langs/htmls/entitys/Gfh_entity_.java
Normal file
35
100_core/src/gplx/langs/htmls/entitys/Gfh_entity_.java
Normal 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.langs.htmls.entitys; import gplx.*; import gplx.langs.*; import gplx.langs.htmls.*;
|
||||
public class Gfh_entity_ {
|
||||
public static final String
|
||||
Nl_str = " "
|
||||
;
|
||||
public static final byte[]
|
||||
Lt_bry = Bry_.new_a7("<"), Gt_bry = Bry_.new_a7(">")
|
||||
, Amp_bry = Bry_.new_a7("&"), Quote_bry = Bry_.new_a7(""")
|
||||
, Apos_num_bry = Bry_.new_a7("'")
|
||||
, Apos_key_bry = Bry_.new_a7("'")
|
||||
, Eq_bry = Bry_.new_a7("=")
|
||||
, Nl_bry = Bry_.new_a7(Nl_str), Space_bry = Bry_.new_a7(" ")
|
||||
, Pipe_bry = Bry_.new_a7("|")
|
||||
, Colon_bry = Bry_.new_a7(":"), Underline_bry = Bry_.new_a7("_"), Asterisk_bry = Bry_.new_a7("*")
|
||||
, Brack_bgn_bry = Bry_.new_a7("["), Brack_end_bry = Bry_.new_a7("]")
|
||||
, Nbsp_num_bry = Bry_.new_a7(" ")
|
||||
;
|
||||
}
|
||||
57
100_core/src/gplx/langs/htmls/entitys/Gfh_entity_itm.java
Normal file
57
100_core/src/gplx/langs/htmls/entitys/Gfh_entity_itm.java
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.langs.htmls.entitys; import gplx.*; import gplx.langs.*; import gplx.langs.htmls.*;
|
||||
public class Gfh_entity_itm { // TS:immutable
|
||||
public Gfh_entity_itm(byte tid, int char_int, byte[] xml_name_bry) {
|
||||
this.tid = tid;
|
||||
this.char_int = char_int;
|
||||
this.u8_bry = gplx.core.intls.Utf16_.Encode_int_to_bry(char_int);
|
||||
this.xml_name_bry = xml_name_bry;
|
||||
this.key_name_len = xml_name_bry.length - 2; // 2 for & and ;
|
||||
}
|
||||
public byte Tid() {return tid;} private final byte tid;
|
||||
public int Char_int() {return char_int;} private final int char_int; // val; EX: 160
|
||||
public byte[] U8_bry() {return u8_bry;} private final byte[] u8_bry; // EX: new byte[] {192, 160}; (C2, A0)
|
||||
public byte[] Xml_name_bry() {return xml_name_bry;} private final byte[] xml_name_bry; // EX: " "
|
||||
public int Key_name_len() {return key_name_len;} private final int key_name_len; // EX: "nbsp".Len
|
||||
|
||||
public void Print_ncr(Bry_bfr bfr) {
|
||||
switch (char_int) {
|
||||
case Byte_ascii.Lt: case Byte_ascii.Gt: case Byte_ascii.Quote: case Byte_ascii.Amp:
|
||||
bfr.Add(xml_name_bry); // NOTE: never write actual char; EX: "<" should be written as "<", not "<"
|
||||
break;
|
||||
default:
|
||||
bfr.Add(Escape_bgn); // &#
|
||||
bfr.Add_int_variable(char_int); // 160
|
||||
bfr.Add_byte(Byte_ascii.Semic); // ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
public void Print_literal(Bry_bfr bfr) {
|
||||
switch (char_int) {
|
||||
case Byte_ascii.Lt: bfr.Add(Gfh_entity_.Lt_bry); break; // NOTE: never write actual char; EX: "<" should be written as "<", not "<"; MW does same; DATE:2014-11-07
|
||||
case Byte_ascii.Gt: bfr.Add(Gfh_entity_.Gt_bry); break;
|
||||
case Byte_ascii.Quote: bfr.Add(Gfh_entity_.Quote_bry); break;
|
||||
case Byte_ascii.Amp: bfr.Add(Gfh_entity_.Amp_bry); break;
|
||||
default: bfr.Add(u8_bry); break; // write literal; EX: "[" not "["
|
||||
}
|
||||
}
|
||||
private static final byte[] Escape_bgn = Bry_.new_a7("&#");
|
||||
public static final byte Tid_name_std = 1, Tid_name_xowa = 2, Tid_num_hex = 3, Tid_num_dec = 4;
|
||||
public static final int Char_int_null = -1;
|
||||
}
|
||||
317
100_core/src/gplx/langs/htmls/entitys/Gfh_entity_trie.java
Normal file
317
100_core/src/gplx/langs/htmls/entitys/Gfh_entity_trie.java
Normal file
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
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.langs.htmls.entitys; import gplx.*; import gplx.langs.*; import gplx.langs.htmls.*;
|
||||
import gplx.core.btries.*;
|
||||
public class Gfh_entity_trie { // TS
|
||||
public static final String // NOTE: top_define; entities needed for <nowiki> escaping
|
||||
Str__xowa_lt = "&xowa_lt;"
|
||||
, Str__xowa_brack_bgn = "&xowa_brack_bgn;"
|
||||
, Str__xowa_brack_end = "&xowa_brack_end;"
|
||||
, Str__xowa_pipe = "&xowa_pipe;"
|
||||
, Str__xowa_apos = "&xowa_apos;"
|
||||
, Str__xowa_colon = "&xowa_colon;"
|
||||
, Str__xowa_underline = "&xowa_underline;"
|
||||
, Str__xowa_asterisk = "&xowa_asterisk;"
|
||||
, Str__xowa_space = "&xowa_space;"
|
||||
, Str__xowa_nl = "&xowa_nl;"
|
||||
, Str__xowa_dash = "&xowa_dash;"
|
||||
;
|
||||
public static final Btrie_slim_mgr Instance = New(); Gfh_entity_trie() {}
|
||||
private static Btrie_slim_mgr New() {// REF.MW: Sanitizer|$wgHtmlEntities; NOTE:added apos
|
||||
Btrie_slim_mgr rv = Btrie_slim_mgr.cs();
|
||||
Add_name(rv, Bool_.Y, 60, Str__xowa_lt);
|
||||
Add_name(rv, Bool_.Y, 91, Str__xowa_brack_bgn);
|
||||
Add_name(rv, Bool_.Y, 93, Str__xowa_brack_end);
|
||||
Add_name(rv, Bool_.Y, 124, Str__xowa_pipe);
|
||||
Add_name(rv, Bool_.Y, 39, Str__xowa_apos);
|
||||
Add_name(rv, Bool_.Y, 58, Str__xowa_colon);
|
||||
Add_name(rv, Bool_.Y, 95, Str__xowa_underline);
|
||||
Add_name(rv, Bool_.Y, 42, Str__xowa_asterisk);
|
||||
Add_name(rv, Bool_.Y, 32, Str__xowa_space);
|
||||
Add_name(rv, Bool_.Y, 10, Str__xowa_nl);
|
||||
Add_name(rv, Bool_.Y, 45, Str__xowa_dash);
|
||||
Add_name(rv, Bool_.N, 39, "'");
|
||||
Add_name(rv, Bool_.N, 193, "Á");
|
||||
Add_name(rv, Bool_.N, 225, "á");
|
||||
Add_name(rv, Bool_.N, 194, "Â");
|
||||
Add_name(rv, Bool_.N, 226, "â");
|
||||
Add_name(rv, Bool_.N, 180, "´");
|
||||
Add_name(rv, Bool_.N, 198, "Æ");
|
||||
Add_name(rv, Bool_.N, 230, "æ");
|
||||
Add_name(rv, Bool_.N, 192, "À");
|
||||
Add_name(rv, Bool_.N, 224, "à");
|
||||
Add_name(rv, Bool_.N, 8501, "ℵ");
|
||||
Add_name(rv, Bool_.N, 913, "Α");
|
||||
Add_name(rv, Bool_.N, 945, "α");
|
||||
Add_name(rv, Bool_.N, 38, "&");
|
||||
Add_name(rv, Bool_.N, 8743, "∧");
|
||||
Add_name(rv, Bool_.N, 8736, "∠");
|
||||
Add_name(rv, Bool_.N, 197, "Å");
|
||||
Add_name(rv, Bool_.N, 229, "å");
|
||||
Add_name(rv, Bool_.N, 8776, "≈");
|
||||
Add_name(rv, Bool_.N, 195, "Ã");
|
||||
Add_name(rv, Bool_.N, 227, "ã");
|
||||
Add_name(rv, Bool_.N, 196, "Ä");
|
||||
Add_name(rv, Bool_.N, 228, "ä");
|
||||
Add_name(rv, Bool_.N, 8222, "„");
|
||||
Add_name(rv, Bool_.N, 914, "Β");
|
||||
Add_name(rv, Bool_.N, 946, "β");
|
||||
Add_name(rv, Bool_.N, 166, "¦");
|
||||
Add_name(rv, Bool_.N, 8226, "•");
|
||||
Add_name(rv, Bool_.N, 8745, "∩");
|
||||
Add_name(rv, Bool_.N, 199, "Ç");
|
||||
Add_name(rv, Bool_.N, 231, "ç");
|
||||
Add_name(rv, Bool_.N, 184, "¸");
|
||||
Add_name(rv, Bool_.N, 162, "¢");
|
||||
Add_name(rv, Bool_.N, 935, "Χ");
|
||||
Add_name(rv, Bool_.N, 967, "χ");
|
||||
Add_name(rv, Bool_.N, 710, "ˆ");
|
||||
Add_name(rv, Bool_.N, 9827, "♣");
|
||||
Add_name(rv, Bool_.N, 8773, "≅");
|
||||
Add_name(rv, Bool_.N, 169, "©");
|
||||
Add_name(rv, Bool_.N, 8629, "↵");
|
||||
Add_name(rv, Bool_.N, 8746, "∪");
|
||||
Add_name(rv, Bool_.N, 164, "¤");
|
||||
Add_name(rv, Bool_.N, 8224, "†");
|
||||
Add_name(rv, Bool_.N, 8225, "‡");
|
||||
Add_name(rv, Bool_.N, 8595, "↓");
|
||||
Add_name(rv, Bool_.N, 8659, "⇓");
|
||||
Add_name(rv, Bool_.N, 176, "°");
|
||||
Add_name(rv, Bool_.N, 916, "Δ");
|
||||
Add_name(rv, Bool_.N, 948, "δ");
|
||||
Add_name(rv, Bool_.N, 9830, "♦");
|
||||
Add_name(rv, Bool_.N, 247, "÷");
|
||||
Add_name(rv, Bool_.N, 201, "É");
|
||||
Add_name(rv, Bool_.N, 233, "é");
|
||||
Add_name(rv, Bool_.N, 202, "Ê");
|
||||
Add_name(rv, Bool_.N, 234, "ê");
|
||||
Add_name(rv, Bool_.N, 200, "È");
|
||||
Add_name(rv, Bool_.N, 232, "è");
|
||||
Add_name(rv, Bool_.N, 8709, "∅");
|
||||
Add_name(rv, Bool_.N, 8195, " ");
|
||||
Add_name(rv, Bool_.N, 8194, " ");
|
||||
Add_name(rv, Bool_.N, 917, "Ε");
|
||||
Add_name(rv, Bool_.N, 949, "ε");
|
||||
Add_name(rv, Bool_.N, 8801, "≡");
|
||||
Add_name(rv, Bool_.N, 919, "Η");
|
||||
Add_name(rv, Bool_.N, 951, "η");
|
||||
Add_name(rv, Bool_.N, 208, "Ð");
|
||||
Add_name(rv, Bool_.N, 240, "ð");
|
||||
Add_name(rv, Bool_.N, 203, "Ë");
|
||||
Add_name(rv, Bool_.N, 235, "ë");
|
||||
Add_name(rv, Bool_.N, 8364, "€");
|
||||
Add_name(rv, Bool_.N, 8707, "∃");
|
||||
Add_name(rv, Bool_.N, 402, "ƒ");
|
||||
Add_name(rv, Bool_.N, 8704, "∀");
|
||||
Add_name(rv, Bool_.N, 189, "½");
|
||||
Add_name(rv, Bool_.N, 188, "¼");
|
||||
Add_name(rv, Bool_.N, 190, "¾");
|
||||
Add_name(rv, Bool_.N, 8260, "⁄");
|
||||
Add_name(rv, Bool_.N, 915, "Γ");
|
||||
Add_name(rv, Bool_.N, 947, "γ");
|
||||
Add_name(rv, Bool_.N, 8805, "≥");
|
||||
Add_name(rv, Bool_.N, 62, ">");
|
||||
Add_name(rv, Bool_.N, 8596, "↔");
|
||||
Add_name(rv, Bool_.N, 8660, "⇔");
|
||||
Add_name(rv, Bool_.N, 9829, "♥");
|
||||
Add_name(rv, Bool_.N, 8230, "…");
|
||||
Add_name(rv, Bool_.N, 205, "Í");
|
||||
Add_name(rv, Bool_.N, 237, "í");
|
||||
Add_name(rv, Bool_.N, 206, "Î");
|
||||
Add_name(rv, Bool_.N, 238, "î");
|
||||
Add_name(rv, Bool_.N, 161, "¡");
|
||||
Add_name(rv, Bool_.N, 204, "Ì");
|
||||
Add_name(rv, Bool_.N, 236, "ì");
|
||||
Add_name(rv, Bool_.N, 8465, "ℑ");
|
||||
Add_name(rv, Bool_.N, 8734, "∞");
|
||||
Add_name(rv, Bool_.N, 8747, "∫");
|
||||
Add_name(rv, Bool_.N, 921, "Ι");
|
||||
Add_name(rv, Bool_.N, 953, "ι");
|
||||
Add_name(rv, Bool_.N, 191, "¿");
|
||||
Add_name(rv, Bool_.N, 8712, "∈");
|
||||
Add_name(rv, Bool_.N, 207, "Ï");
|
||||
Add_name(rv, Bool_.N, 239, "ï");
|
||||
Add_name(rv, Bool_.N, 922, "Κ");
|
||||
Add_name(rv, Bool_.N, 954, "κ");
|
||||
Add_name(rv, Bool_.N, 923, "Λ");
|
||||
Add_name(rv, Bool_.N, 955, "λ");
|
||||
Add_name(rv, Bool_.N, 9001, "⟨");
|
||||
Add_name(rv, Bool_.N, 171, "«");
|
||||
Add_name(rv, Bool_.N, 8592, "←");
|
||||
Add_name(rv, Bool_.N, 8656, "⇐");
|
||||
Add_name(rv, Bool_.N, 8968, "⌈");
|
||||
Add_name(rv, Bool_.N, 8220, "“");
|
||||
Add_name(rv, Bool_.N, 8804, "≤");
|
||||
Add_name(rv, Bool_.N, 8970, "⌊");
|
||||
Add_name(rv, Bool_.N, 8727, "∗");
|
||||
Add_name(rv, Bool_.N, 9674, "◊");
|
||||
Add_name(rv, Bool_.N, 8206, "‎");
|
||||
Add_name(rv, Bool_.N, 8249, "‹");
|
||||
Add_name(rv, Bool_.N, 8216, "‘");
|
||||
Add_name(rv, Bool_.N, 60, "<");
|
||||
Add_name(rv, Bool_.N, 175, "¯");
|
||||
Add_name(rv, Bool_.N, 8212, "—");
|
||||
Add_name(rv, Bool_.N, 181, "µ");
|
||||
Add_name(rv, Bool_.N, 183, "·");
|
||||
Add_name(rv, Bool_.N, 8722, "−");
|
||||
Add_name(rv, Bool_.N, 924, "Μ");
|
||||
Add_name(rv, Bool_.N, 956, "μ");
|
||||
Add_name(rv, Bool_.N, 8711, "∇");
|
||||
Add_name(rv, Bool_.N, 160, " ");
|
||||
Add_name(rv, Bool_.N, 8211, "–");
|
||||
Add_name(rv, Bool_.N, 8800, "≠");
|
||||
Add_name(rv, Bool_.N, 8715, "∋");
|
||||
Add_name(rv, Bool_.N, 172, "¬");
|
||||
Add_name(rv, Bool_.N, 8713, "∉");
|
||||
Add_name(rv, Bool_.N, 8836, "⊄");
|
||||
Add_name(rv, Bool_.N, 209, "Ñ");
|
||||
Add_name(rv, Bool_.N, 241, "ñ");
|
||||
Add_name(rv, Bool_.N, 925, "Ν");
|
||||
Add_name(rv, Bool_.N, 957, "ν");
|
||||
Add_name(rv, Bool_.N, 211, "Ó");
|
||||
Add_name(rv, Bool_.N, 243, "ó");
|
||||
Add_name(rv, Bool_.N, 212, "Ô");
|
||||
Add_name(rv, Bool_.N, 244, "ô");
|
||||
Add_name(rv, Bool_.N, 338, "Œ");
|
||||
Add_name(rv, Bool_.N, 339, "œ");
|
||||
Add_name(rv, Bool_.N, 210, "Ò");
|
||||
Add_name(rv, Bool_.N, 242, "ò");
|
||||
Add_name(rv, Bool_.N, 8254, "‾");
|
||||
Add_name(rv, Bool_.N, 937, "Ω");
|
||||
Add_name(rv, Bool_.N, 969, "ω");
|
||||
Add_name(rv, Bool_.N, 927, "Ο");
|
||||
Add_name(rv, Bool_.N, 959, "ο");
|
||||
Add_name(rv, Bool_.N, 8853, "⊕");
|
||||
Add_name(rv, Bool_.N, 8744, "∨");
|
||||
Add_name(rv, Bool_.N, 170, "ª");
|
||||
Add_name(rv, Bool_.N, 186, "º");
|
||||
Add_name(rv, Bool_.N, 216, "Ø");
|
||||
Add_name(rv, Bool_.N, 248, "ø");
|
||||
Add_name(rv, Bool_.N, 213, "Õ");
|
||||
Add_name(rv, Bool_.N, 245, "õ");
|
||||
Add_name(rv, Bool_.N, 8855, "⊗");
|
||||
Add_name(rv, Bool_.N, 214, "Ö");
|
||||
Add_name(rv, Bool_.N, 246, "ö");
|
||||
Add_name(rv, Bool_.N, 182, "¶");
|
||||
Add_name(rv, Bool_.N, 8706, "∂");
|
||||
Add_name(rv, Bool_.N, 8240, "‰");
|
||||
Add_name(rv, Bool_.N, 8869, "⊥");
|
||||
Add_name(rv, Bool_.N, 934, "Φ");
|
||||
Add_name(rv, Bool_.N, 966, "φ");
|
||||
Add_name(rv, Bool_.N, 928, "Π");
|
||||
Add_name(rv, Bool_.N, 960, "π");
|
||||
Add_name(rv, Bool_.N, 982, "ϖ");
|
||||
Add_name(rv, Bool_.N, 177, "±");
|
||||
Add_name(rv, Bool_.N, 163, "£");
|
||||
Add_name(rv, Bool_.N, 8242, "′");
|
||||
Add_name(rv, Bool_.N, 8243, "″");
|
||||
Add_name(rv, Bool_.N, 8719, "∏");
|
||||
Add_name(rv, Bool_.N, 8733, "∝");
|
||||
Add_name(rv, Bool_.N, 936, "Ψ");
|
||||
Add_name(rv, Bool_.N, 968, "ψ");
|
||||
Add_name(rv, Bool_.N, 34, """);
|
||||
Add_name(rv, Bool_.N, 8730, "√");
|
||||
Add_name(rv, Bool_.N, 9002, "⟩");
|
||||
Add_name(rv, Bool_.N, 187, "»");
|
||||
Add_name(rv, Bool_.N, 8594, "→");
|
||||
Add_name(rv, Bool_.N, 8658, "⇒");
|
||||
Add_name(rv, Bool_.N, 8969, "⌉");
|
||||
Add_name(rv, Bool_.N, 8221, "”");
|
||||
Add_name(rv, Bool_.N, 8476, "ℜ");
|
||||
Add_name(rv, Bool_.N, 174, "®");
|
||||
Add_name(rv, Bool_.N, 8971, "⌋");
|
||||
Add_name(rv, Bool_.N, 929, "Ρ");
|
||||
Add_name(rv, Bool_.N, 961, "ρ");
|
||||
Add_name(rv, Bool_.N, 8207, "‏");
|
||||
Add_name(rv, Bool_.N, 8250, "›");
|
||||
Add_name(rv, Bool_.N, 8217, "’");
|
||||
Add_name(rv, Bool_.N, 8218, "‚");
|
||||
Add_name(rv, Bool_.N, 352, "Š");
|
||||
Add_name(rv, Bool_.N, 353, "š");
|
||||
Add_name(rv, Bool_.N, 8901, "⋅");
|
||||
Add_name(rv, Bool_.N, 167, "§");
|
||||
Add_name(rv, Bool_.N, 173, "­");
|
||||
Add_name(rv, Bool_.N, 931, "Σ");
|
||||
Add_name(rv, Bool_.N, 963, "σ");
|
||||
Add_name(rv, Bool_.N, 962, "ς");
|
||||
Add_name(rv, Bool_.N, 8764, "∼");
|
||||
Add_name(rv, Bool_.N, 9824, "♠");
|
||||
Add_name(rv, Bool_.N, 8834, "⊂");
|
||||
Add_name(rv, Bool_.N, 8838, "⊆");
|
||||
Add_name(rv, Bool_.N, 8721, "∑");
|
||||
Add_name(rv, Bool_.N, 8835, "⊃");
|
||||
Add_name(rv, Bool_.N, 185, "¹");
|
||||
Add_name(rv, Bool_.N, 178, "²");
|
||||
Add_name(rv, Bool_.N, 179, "³");
|
||||
Add_name(rv, Bool_.N, 8839, "⊇");
|
||||
Add_name(rv, Bool_.N, 223, "ß");
|
||||
Add_name(rv, Bool_.N, 932, "Τ");
|
||||
Add_name(rv, Bool_.N, 964, "τ");
|
||||
Add_name(rv, Bool_.N, 8756, "∴");
|
||||
Add_name(rv, Bool_.N, 920, "Θ");
|
||||
Add_name(rv, Bool_.N, 952, "θ");
|
||||
Add_name(rv, Bool_.N, 977, "ϑ");
|
||||
Add_name(rv, Bool_.N, 8201, " ");
|
||||
Add_name(rv, Bool_.N, 222, "Þ");
|
||||
Add_name(rv, Bool_.N, 254, "þ");
|
||||
Add_name(rv, Bool_.N, 732, "˜");
|
||||
Add_name(rv, Bool_.N, 215, "×");
|
||||
Add_name(rv, Bool_.N, 8482, "™");
|
||||
Add_name(rv, Bool_.N, 218, "Ú");
|
||||
Add_name(rv, Bool_.N, 250, "ú");
|
||||
Add_name(rv, Bool_.N, 8593, "↑");
|
||||
Add_name(rv, Bool_.N, 8657, "⇑");
|
||||
Add_name(rv, Bool_.N, 219, "Û");
|
||||
Add_name(rv, Bool_.N, 251, "û");
|
||||
Add_name(rv, Bool_.N, 217, "Ù");
|
||||
Add_name(rv, Bool_.N, 249, "ù");
|
||||
Add_name(rv, Bool_.N, 168, "¨");
|
||||
Add_name(rv, Bool_.N, 978, "ϒ");
|
||||
Add_name(rv, Bool_.N, 933, "Υ");
|
||||
Add_name(rv, Bool_.N, 965, "υ");
|
||||
Add_name(rv, Bool_.N, 220, "Ü");
|
||||
Add_name(rv, Bool_.N, 252, "ü");
|
||||
Add_name(rv, Bool_.N, 8472, "℘");
|
||||
Add_name(rv, Bool_.N, 926, "Ξ");
|
||||
Add_name(rv, Bool_.N, 958, "ξ");
|
||||
Add_name(rv, Bool_.N, 221, "Ý");
|
||||
Add_name(rv, Bool_.N, 253, "ý");
|
||||
Add_name(rv, Bool_.N, 165, "¥");
|
||||
Add_name(rv, Bool_.N, 376, "Ÿ");
|
||||
Add_name(rv, Bool_.N, 255, "ÿ");
|
||||
Add_name(rv, Bool_.N, 918, "Ζ");
|
||||
Add_name(rv, Bool_.N, 950, "ζ");
|
||||
Add_name(rv, Bool_.N, 8205, "‍");
|
||||
Add_name(rv, Bool_.N, 8204, "‌");
|
||||
Add_prefix(rv, Gfh_entity_itm.Tid_num_hex, "#x");
|
||||
Add_prefix(rv, Gfh_entity_itm.Tid_num_hex, "#X");
|
||||
Add_prefix(rv, Gfh_entity_itm.Tid_num_dec, "#");
|
||||
return rv;
|
||||
}
|
||||
private static void Add_name(Btrie_slim_mgr trie, boolean tid_is_xowa, int char_int, String xml_name_str) {
|
||||
byte itm_tid = tid_is_xowa ? Gfh_entity_itm.Tid_name_xowa : Gfh_entity_itm.Tid_name_std;
|
||||
byte[] xml_name_bry = Bry_.new_a7(xml_name_str);
|
||||
byte[] key = Bry_.Mid(xml_name_bry, 1, xml_name_bry.length); // ignore & for purpose of trie; EX: "amp;"; NOTE: must keep trailing ";" else "& " will be valid;
|
||||
trie.Add_obj(key, new Gfh_entity_itm(itm_tid, char_int, xml_name_bry));
|
||||
}
|
||||
private static void Add_prefix(Btrie_slim_mgr trie, byte prefix_type, String prefix) {
|
||||
byte[] prefix_ary = Bry_.new_u8(prefix);
|
||||
Gfh_entity_itm itm = new Gfh_entity_itm(prefix_type, Gfh_entity_itm.Char_int_null, prefix_ary);
|
||||
trie.Add_obj(prefix_ary, itm);
|
||||
}
|
||||
}
|
||||
65
100_core/src/gplx/langs/regxs/Regx_adp.java
Normal file
65
100_core/src/gplx/langs/regxs/Regx_adp.java
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
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.langs.regxs; import gplx.*; import gplx.langs.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
public class Regx_adp {
|
||||
@gplx.Internal protected Regx_adp(String regx) {Pattern_(regx);}
|
||||
public String Pattern() {return pattern;} public Regx_adp Pattern_(String val) {pattern = val; Under_sync(); return this;} private String pattern;
|
||||
public boolean Pattern_is_invalid() {return pattern_is_invalid;} private boolean pattern_is_invalid = false;
|
||||
public Regx_match[] Match_all(String text, int bgn) {
|
||||
int idx = bgn;
|
||||
List_adp rv = List_adp_.New();
|
||||
int len = String_.Len(text);
|
||||
while (idx <= len) { // NOTE: must be <= not < else "a?" will return null instead of ""; PAGE:en.d:民; DATE:2015-01-30
|
||||
Regx_match match = this.Match(text, idx);
|
||||
if (match.Rslt_none()) break;
|
||||
rv.Add(match);
|
||||
int find_bgn = match.Find_bgn();
|
||||
int find_len = match.Find_len();
|
||||
idx = find_len == 0 // find_bgn == find_end
|
||||
? find_bgn + 1 // add 1 to resume search from next char; DATE:2014-09-02
|
||||
: find_bgn + find_len // otherwise search after find_end
|
||||
;
|
||||
}
|
||||
return (Regx_match[])rv.To_ary(Regx_match.class);
|
||||
}
|
||||
private Pattern under;
|
||||
void Under_sync() {
|
||||
try {under = Pattern.compile(pattern, Pattern.DOTALL | Pattern.UNICODE_CHARACTER_CLASS);} // JRE.7:UNICODE_CHARACTER_CLASS; added during %w fix for en.w:A#; DATE:2015-06-10
|
||||
catch (Exception e) { // NOTE: if invalid, then default to empty pattern (which should return nothing); EX:d:〆る generates [^]; DATE:2013-10-20
|
||||
pattern_is_invalid = true;
|
||||
under = Pattern.compile("", Pattern.DOTALL | Pattern.UNICODE_CHARACTER_CLASS);
|
||||
}
|
||||
}
|
||||
public Regx_match Match(String input, int bgn) {
|
||||
Matcher match = under.matcher(input);
|
||||
boolean success = match.find(bgn);
|
||||
int match_bgn = success ? match.start() : String_.Find_none;
|
||||
int match_end = success ? match.end() : String_.Find_none;
|
||||
Regx_group[] ary = Regx_group.Ary_empty;
|
||||
int groups_len = match.groupCount();
|
||||
if (success && groups_len > 0) {
|
||||
ary = new Regx_group[groups_len];
|
||||
for (int i = 0; i < groups_len; i++)
|
||||
ary[i] = new Regx_group(true, match.start(i + 1), match.end(i + 1), match.group(i + 1));
|
||||
}
|
||||
return new Regx_match(success, match_bgn, match_end, ary);
|
||||
}
|
||||
public String ReplaceAll(String input, String replace) {return under.matcher(input).replaceAll(replace);}
|
||||
}
|
||||
43
100_core/src/gplx/langs/regxs/Regx_adp_.java
Normal file
43
100_core/src/gplx/langs/regxs/Regx_adp_.java
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
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.langs.regxs; import gplx.*; import gplx.langs.*;
|
||||
public class Regx_adp_ {
|
||||
public static Regx_adp new_(String pattern) {return new Regx_adp(pattern);}
|
||||
public static List_adp Find_all(String input, String find) {
|
||||
Regx_adp regx = Regx_adp_.new_(find);
|
||||
int idx = 0;
|
||||
List_adp rv = List_adp_.New();
|
||||
while (true) {
|
||||
Regx_match match = regx.Match(input, idx);
|
||||
if (match.Rslt_none()) break;
|
||||
rv.Add(match);
|
||||
int findBgn = match.Find_bgn();
|
||||
idx = findBgn + match.Find_len();
|
||||
if (idx > String_.Len(input)) break;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static String Replace(String raw, String regx_str, String replace) {
|
||||
Regx_adp regx = Regx_adp_.new_(regx_str);
|
||||
return regx.ReplaceAll(raw, replace);
|
||||
}
|
||||
public static boolean Match(String input, String pattern) {
|
||||
Regx_adp rv = new Regx_adp(pattern);
|
||||
return rv.Match(input, 0).Rslt();
|
||||
}
|
||||
}
|
||||
93
100_core/src/gplx/langs/regxs/Regx_adp__tst.java
Normal file
93
100_core/src/gplx/langs/regxs/Regx_adp__tst.java
Normal 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.langs.regxs; import gplx.*; import gplx.langs.*;
|
||||
import org.junit.*; import gplx.core.tests.*;
|
||||
public class Regx_adp__tst implements TfdsEqListItmStr {
|
||||
@Test public void Match() {
|
||||
tst_Match("a", "a", true); // basic
|
||||
tst_Match("a", "b", false); // matchNot
|
||||
tst_Match("a", "ab", true); // matchPart
|
||||
tst_Match("a\\+b", "a+b", true); // matchEscape
|
||||
tst_Match("[^a]", "b", true); // charSet_negate
|
||||
} void tst_Match(String find, String input, boolean expd) {Tfds.Eq(expd, Regx_adp_.Match(input, find));}
|
||||
@Test public void Match_all() {
|
||||
tst_Match_all("#REDIRECT [[Template:Error]]", "^\\p{Nd}*", 1); // handle match = true but len = 0; DATE:2013-04-11
|
||||
tst_Match_all("a", "$", 1); // $ should match once, not zero; DATE:2014-09-02
|
||||
} void tst_Match_all(String input, String regx, int expd) {Tfds.Eq(expd, Regx_adp_.new_(regx).Match_all(input, 0).length);}
|
||||
@Test public void Replace() {
|
||||
tst_Replace("ab", "a", "b", "bb"); // basic
|
||||
tst_Replace("ab", "c", "b", "ab"); // replaceNot
|
||||
tst_Replace("aba", "a", "b", "bbb"); // replaceMultiple
|
||||
} void tst_Replace(String input, String find, String replace, String expd) {Tfds.Eq(expd, Regx_adp_.Replace(input, find, replace));}
|
||||
@Test public void Match_WholeWord() {
|
||||
tst_WholeWord("a", "ab a", true); // pass a
|
||||
tst_WholeWord("a", "ab c", false); // fail ab
|
||||
tst_WholeWord("a", "a_", false); // fail a_
|
||||
tst_WholeWord("[a]", "a [a] c", true); // pass [a]
|
||||
tst_WholeWord("[a]", "a[a]c", false); // fail a[a]c
|
||||
} void tst_WholeWord(String regx, String text, boolean expd) {Tfds.Eq(expd, Regx_adp_.Match(text, Regx_bldr.WholeWord(regx)));}
|
||||
@Test public void Match_As() {
|
||||
tst_Regx("public static [A-Za-z0-9_]+ as_\\(Object obj\\)", "public static Obj1 as_(Object obj) {return obj instanceof Obj1 ? (Obj1)obj : null;}", true);
|
||||
tst_Regx("public static [A-Za-z0-9_]+ as_\\(Object obj\\)", "public static boolean Asterisk(Object obj) {}", false);
|
||||
} void tst_Regx(String regx, String text, boolean expd) {Tfds.Eq(expd, Regx_adp_.Match(text, regx));}
|
||||
@Test public void Find() {
|
||||
tst_Matches("b", "a b c b a", match_(2, 1), match_(6, 1));
|
||||
tst_Matches("d", "a b c b a");
|
||||
tst_Matches("b", "a b c b a b b", matches_(2, 6, 10, 12)); // BUGFIX: multiple entries did not work b/c of += instead of +
|
||||
}
|
||||
@Test public void Groups() {
|
||||
tst_Groups("abc def ghi dz", "(d\\p{L}+)", "def", "dz");
|
||||
}
|
||||
Regx_match[] matches_(int... bgnAry) {
|
||||
int aryLen = Array_.Len(bgnAry);
|
||||
Regx_match[] rv = new Regx_match[aryLen];
|
||||
for (int i = 0; i < aryLen; i++)
|
||||
rv[i] = match_(bgnAry[i]);
|
||||
return rv;
|
||||
}
|
||||
Regx_match match_(int bgn) {return match_(bgn, Int_.Min_value);}
|
||||
Regx_match match_(int bgn, int len) {return new Regx_match(true, bgn, bgn + len, Regx_group.Ary_empty);}
|
||||
void tst_Matches(String find, String input, Regx_match... expd) {
|
||||
List_adp expdList = Array_.To_list(expd);
|
||||
List_adp actlList = Regx_adp_.Find_all(input, find);
|
||||
Tfds.Eq_list(expdList, actlList, this);
|
||||
}
|
||||
void tst_Groups(String text, String regx, String... expd) {
|
||||
Regx_adp regx_mgr = Regx_adp_.new_(regx);
|
||||
Regx_match[] rslts = regx_mgr.Match_all(text, 0);
|
||||
Tfds.Eq_ary_str(expd, To_ary(rslts));
|
||||
}
|
||||
String[] To_ary(Regx_match[] ary) {
|
||||
List_adp rv = List_adp_.New();
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
Regx_match itm = ary[i];
|
||||
int cap_len = itm.Groups().length;
|
||||
for (int j = 0; j < cap_len; j++) {
|
||||
rv.Add(itm.Groups()[j].Val());
|
||||
}
|
||||
}
|
||||
return rv.To_str_ary();
|
||||
}
|
||||
public String To_str(Object curObj, Object expdObj) {
|
||||
Regx_match cur = (Regx_match)curObj, expd = (Regx_match)expdObj;
|
||||
String rv = "bgn=" + cur.Find_bgn();
|
||||
if (expd != null && expd.Find_len() != Int_.Min_value) rv += " len=" + cur.Find_len();
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
62
100_core/src/gplx/langs/regxs/Regx_bldr.java
Normal file
62
100_core/src/gplx/langs/regxs/Regx_bldr.java
Normal 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.langs.regxs; import gplx.*; import gplx.langs.*;
|
||||
import gplx.core.strings.*;
|
||||
public class Regx_bldr {
|
||||
public static String Includes(String characters) {return String_.Concat_any(Regx_bldr.Tkn_CharSetBegin, characters, Regx_bldr.Tkn_CharSetEnd);}
|
||||
public static String Excludes(String characters) {return String_.Concat_any(Regx_bldr.Tkn_CharSetBegin, Regx_bldr.Tkn_Not, characters, Regx_bldr.Tkn_CharSetEnd);}
|
||||
public static String WholeWord(String word) {return String_.Concat_any("(?<![A-Za-z0-9_])", EscapeAll(word), "(?![A-Za-z0-9_])");}
|
||||
public static String EscapeAll(String text) {
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
int len = String_.Len(text);
|
||||
for (int i = 0; i < len; i++) {
|
||||
char c = String_.CharAt(text, i);
|
||||
if (RegxChar_chk(c))
|
||||
sb.Add(Regx_bldr.Tkn_Escape);
|
||||
sb.Add(c);
|
||||
}
|
||||
return sb.To_str();
|
||||
}
|
||||
public static boolean RegxChar_chk(char c) {
|
||||
return
|
||||
( c == Regx_bldr.Tkn_Escape || c == Regx_bldr.Tkn_Or
|
||||
|| c == Regx_bldr.Tkn_LineBegin || c == Regx_bldr.Tkn_LineEnd
|
||||
|| c == Regx_bldr.Tkn_GroupBegin || c == Regx_bldr.Tkn_GroupEnd
|
||||
|| c == Regx_bldr.Tkn_RepBegin || c == Regx_bldr.Tkn_RepEnd
|
||||
|| c == Regx_bldr.Tkn_Wild_0Plus || c == Regx_bldr.Tkn_Wild_1Plus || c == Regx_bldr.Tkn_Wild_0or1
|
||||
|| c == Regx_bldr.Tkn_CharSetBegin || c == Regx_bldr.Tkn_CharSetEnd
|
||||
);
|
||||
}
|
||||
public static final char
|
||||
Tkn_LineBegin = '^'
|
||||
, Tkn_LineEnd = '$'
|
||||
, Tkn_AnyChar = '.' // except newline
|
||||
, Tkn_Wild_0Plus = '*'
|
||||
, Tkn_Wild_1Plus = '+'
|
||||
, Tkn_Wild_0or1 = '?'
|
||||
, Tkn_CharSetBegin = '['
|
||||
, Tkn_CharSetEnd = ']'
|
||||
, Tkn_GroupBegin = '('
|
||||
, Tkn_GroupEnd = ')'
|
||||
, Tkn_RepBegin = '{'
|
||||
, Tkn_RepEnd = '}'
|
||||
, Tkn_Not = '^'
|
||||
, Tkn_Or = '|'
|
||||
, Tkn_Escape = '\\'
|
||||
;
|
||||
}
|
||||
26
100_core/src/gplx/langs/regxs/Regx_group.java
Normal file
26
100_core/src/gplx/langs/regxs/Regx_group.java
Normal 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.langs.regxs; import gplx.*; import gplx.langs.*;
|
||||
public class Regx_group {
|
||||
public Regx_group(boolean rslt, int bgn, int end, String val) {this.rslt = rslt; this.bgn = bgn; this.end = end; this.val = val;}
|
||||
public boolean Rslt() {return rslt;} private boolean rslt;
|
||||
public int Bgn() {return bgn;} int bgn;
|
||||
public int End() {return end;} int end;
|
||||
public String Val() {return val;} private String val;
|
||||
public static final Regx_group[] Ary_empty = new Regx_group[0];
|
||||
}
|
||||
28
100_core/src/gplx/langs/regxs/Regx_match.java
Normal file
28
100_core/src/gplx/langs/regxs/Regx_match.java
Normal 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.langs.regxs; import gplx.*; import gplx.langs.*;
|
||||
public class Regx_match {
|
||||
public Regx_match(boolean rslt, int find_bgn, int find_end, Regx_group[] groups) {this.rslt = rslt; this.find_bgn = find_bgn; this.find_end = find_end; this.groups = groups;}
|
||||
public boolean Rslt() {return rslt;} private boolean rslt;
|
||||
public boolean Rslt_none() {return !rslt;} // NOTE: was "|| find_end - find_bgn == 0"; DATE:2013-04-11; DATE:2014-09-02
|
||||
public int Find_bgn() {return find_bgn;} int find_bgn;
|
||||
public int Find_end() {return find_end;} int find_end;
|
||||
public int Find_len() {return find_end - find_bgn;}
|
||||
public Regx_group[] Groups() {return groups;} Regx_group[] groups = Regx_group.Ary_empty;
|
||||
public static final Regx_match[] Ary_empty = new Regx_match[0];
|
||||
}
|
||||
56
100_core/src/gplx/langs/xmls/HierStrBldr.java
Normal file
56
100_core/src/gplx/langs/xmls/HierStrBldr.java
Normal 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.langs.xmls; import gplx.*; import gplx.langs.*;
|
||||
import gplx.core.strings.*; import gplx.core.envs.*;
|
||||
public class HierStrBldr {
|
||||
public String Root() {return root;} public HierStrBldr Root_(String v) {root = v; return this;} private String root;
|
||||
public Io_url RootAsIoUrl() {return Io_url_.new_dir_(root);}
|
||||
public String DirFmt() {return dirFmt;} private String dirFmt;
|
||||
public String DirSpr() {return dirSpr;} private String dirSpr = Op_sys.Cur().Fsys_dir_spr_str();
|
||||
public String FilFmt() {return filFmt;} private String filFmt;
|
||||
public String NumFmt() {return numFmt;} private String numFmt;
|
||||
public int[] FilCountMaxs() {return filCountMaxs;} int[] filCountMaxs;
|
||||
public Io_url GenStrIdxOnlyAsoUrl(int idx) {return Io_url_.new_fil_(GenStrIdxOnly(idx));}
|
||||
public String GenStrIdxOnly(int idx) {return GenStr(String_.Ary_empty, idx);}
|
||||
public Io_url GenStrAsIoUrl(String[] subDirs, int idx) {
|
||||
return Io_url_.new_fil_(GenStr(subDirs, idx));
|
||||
}
|
||||
String GenStr(String[] subDirs, int idx) {
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
sb.Add(root);
|
||||
for (String subDir : subDirs)
|
||||
sb.Add(subDir).Add(dirSpr);
|
||||
int multiple = 1;
|
||||
int[] multipleAry = new int[filCountMaxs.length];
|
||||
for (int i = filCountMaxs.length - 1; i >= 0; i--) {
|
||||
multiple *= filCountMaxs[i];
|
||||
multipleAry[i] = (idx / multiple) * multiple; // NOTE: rounds down to multiple; EX: 11 -> 10
|
||||
}
|
||||
for (int i = 0; i < multipleAry.length; i++)
|
||||
sb.Add_fmt(dirFmt, Int_.To_str_fmt(multipleAry[i], numFmt));
|
||||
sb.Add_fmt(filFmt, Int_.To_str_fmt(idx, numFmt));
|
||||
return sb.To_str();
|
||||
}
|
||||
public HierStrBldr Ctor_io(Io_url root, String dirFmt, String filFmt, String numFmt, int... filCountMaxs) {
|
||||
this.Ctor(root.Raw(), dirFmt + dirSpr, filFmt, numFmt, filCountMaxs);
|
||||
return this;
|
||||
}
|
||||
public void Ctor(String root, String dirFmt, String filFmt, String numFmt, int... filCountMaxs) {
|
||||
this.root = root; this.dirFmt = dirFmt; this.filFmt = filFmt; this.numFmt = numFmt; this.filCountMaxs = filCountMaxs;
|
||||
}
|
||||
}
|
||||
47
100_core/src/gplx/langs/xmls/HierStrBldr_tst.java
Normal file
47
100_core/src/gplx/langs/xmls/HierStrBldr_tst.java
Normal 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.langs.xmls; import gplx.*; import gplx.langs.*;
|
||||
import org.junit.*;
|
||||
import gplx.core.ios.*; import gplx.core.texts.*;
|
||||
public class HierStrBldr_tst {
|
||||
@Before public void setup() {bldr = new HierStrBldr();} HierStrBldr bldr;
|
||||
@Test public void Hier0() {
|
||||
bldr.Ctor("/root/", "dir_{0}/", "idx_{0}.csv", "000");
|
||||
tst_MakeName( 0, "/root/idx_000.csv");
|
||||
tst_MakeName( 1, "/root/idx_001.csv");
|
||||
tst_MakeName(10, "/root/idx_010.csv");
|
||||
}
|
||||
@Test public void Hier1() {
|
||||
bldr.Ctor("/root/", "dir_{0}/", "idx_{0}.csv", "000", 10);
|
||||
tst_MakeName( 0, "/root/dir_000/idx_000.csv");
|
||||
tst_MakeName( 1, "/root/dir_000/idx_001.csv");
|
||||
tst_MakeName(10, "/root/dir_010/idx_010.csv");
|
||||
}
|
||||
@Test public void Hier2() {
|
||||
bldr.Ctor("/root/", "dir_{0}/", "idx_{0}.csv", "000", 5, 10);
|
||||
tst_MakeName( 0, "/root/dir_000/dir_000/idx_000.csv");
|
||||
tst_MakeName( 1, "/root/dir_000/dir_000/idx_001.csv");
|
||||
tst_MakeName( 10, "/root/dir_000/dir_010/idx_010.csv");
|
||||
tst_MakeName( 49, "/root/dir_000/dir_040/idx_049.csv");
|
||||
tst_MakeName( 50, "/root/dir_050/dir_050/idx_050.csv");
|
||||
tst_MakeName( 99, "/root/dir_050/dir_090/idx_099.csv");
|
||||
tst_MakeName(100, "/root/dir_100/dir_100/idx_100.csv");
|
||||
tst_MakeName(110, "/root/dir_100/dir_110/idx_110.csv");
|
||||
}
|
||||
void tst_MakeName(int val, String expd) {Tfds.Eq(expd, bldr.GenStrIdxOnly(val));}
|
||||
}
|
||||
24
100_core/src/gplx/langs/xmls/XmlAtr.java
Normal file
24
100_core/src/gplx/langs/xmls/XmlAtr.java
Normal 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.langs.xmls; import gplx.*; import gplx.langs.*;
|
||||
import org.w3c.dom.Node;
|
||||
public class XmlAtr {
|
||||
public String Name() {return xatr.getNodeName();}
|
||||
public String Value() {return xatr.getNodeValue();}
|
||||
@gplx.Internal protected XmlAtr(Node xatr) {this.xatr = xatr;} Node xatr;
|
||||
}
|
||||
37
100_core/src/gplx/langs/xmls/XmlAtrList.java
Normal file
37
100_core/src/gplx/langs/xmls/XmlAtrList.java
Normal 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.langs.xmls; import gplx.*; import gplx.langs.*;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
public class XmlAtrList {
|
||||
public int Count() {return list == null ? 0 : list.getLength();}
|
||||
public String FetchValOr(String key, String or) {
|
||||
Node xatr = list.getNamedItem(key);
|
||||
return (xatr == null) ? or : xatr.getNodeValue();
|
||||
}
|
||||
public XmlAtr Fetch(String key) {
|
||||
Node xatr = list.getNamedItem(key); if (xatr == null) throw Err_.new_missing_key(key);
|
||||
return new XmlAtr(xatr);
|
||||
}
|
||||
public XmlAtr Fetch_or_null(String key) {
|
||||
Node xatr = list.getNamedItem(key); if (xatr == null) return null;
|
||||
return new XmlAtr(xatr);
|
||||
}
|
||||
public XmlAtr Get_at(int i) {return list == null ? null : new XmlAtr(list.item(i));}
|
||||
@gplx.Internal protected XmlAtrList(NamedNodeMap list) {this.list = list;} NamedNodeMap list;
|
||||
}
|
||||
24
100_core/src/gplx/langs/xmls/XmlDoc.java
Normal file
24
100_core/src/gplx/langs/xmls/XmlDoc.java
Normal 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.langs.xmls; import gplx.*; import gplx.langs.*;
|
||||
import org.w3c.dom.Document;
|
||||
public class XmlDoc {
|
||||
public XmlNde Root() {return new XmlNde(xdoc.getDocumentElement());}
|
||||
@gplx.Internal protected XmlDoc(Document xdoc) {this.xdoc = xdoc;} Document xdoc;
|
||||
}
|
||||
//#}
|
||||
53
100_core/src/gplx/langs/xmls/XmlDoc_.java
Normal file
53
100_core/src/gplx/langs/xmls/XmlDoc_.java
Normal 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.langs.xmls; import gplx.*; import gplx.langs.*;
|
||||
import gplx.Io_url;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
public class XmlDoc_ {
|
||||
public static XmlDoc parse(String raw) {return new XmlDoc(doc_(raw));}
|
||||
static Document doc_(String raw) {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder bldr = null;
|
||||
try {bldr = factory.newDocumentBuilder();}
|
||||
catch (ParserConfigurationException e) {throw Err_.new_exc(e, "xml", "failed to create newDocumentBuilder");}
|
||||
StringReader reader = new StringReader(raw);
|
||||
InputSource source = new InputSource(reader);
|
||||
Document doc = null;
|
||||
try {doc = bldr.parse(source);}
|
||||
catch (SAXException e) {throw Err_.new_exc(e, "xml", "failed to parse xml", "raw", raw);}
|
||||
catch (IOException e) {throw Err_.new_exc(e, "xml", "failed to parse xml", "raw", raw);}
|
||||
return doc;
|
||||
}
|
||||
public static final String Err_XmlException = "gplx.xmls.XmlException";
|
||||
}
|
||||
//#}
|
||||
71
100_core/src/gplx/langs/xmls/XmlDoc_tst.java
Normal file
71
100_core/src/gplx/langs/xmls/XmlDoc_tst.java
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.langs.xmls; import gplx.*; import gplx.langs.*;
|
||||
import org.junit.*;
|
||||
public class XmlDoc_tst {
|
||||
String xml; XmlDoc xdoc; XmlNde xnde;
|
||||
@Test public void parse() {
|
||||
xml = String_.Concat("<root/>");
|
||||
xdoc = XmlDoc_.parse(xml);
|
||||
Tfds.Eq("root", xdoc.Root().Name());
|
||||
Tfds.Eq(true, xdoc.Root().NdeType_element());
|
||||
}
|
||||
@Test public void Xml_outer() {
|
||||
xml = String_.Concat
|
||||
( "<root>"
|
||||
, "<a>"
|
||||
, "<b/>"
|
||||
, "<b/>"
|
||||
, "</a>"
|
||||
, "</root>"
|
||||
);
|
||||
xdoc = XmlDoc_.parse(xml);
|
||||
xnde = xdoc.Root().SubNdes().Get_at(0);
|
||||
Tfds.Eq("a", xnde.Name());
|
||||
Tfds.Eq("<a><b/><b/></a>", xnde.Xml_outer());
|
||||
}
|
||||
@Test public void Text_inner() {
|
||||
xml = String_.Concat
|
||||
( "<root>"
|
||||
, "<a>"
|
||||
, "test me"
|
||||
, "</a>"
|
||||
, "</root>"
|
||||
);
|
||||
xdoc = XmlDoc_.parse(xml);
|
||||
xnde = xdoc.Root().SubNdes().Get_at(0);
|
||||
Tfds.Eq("a", xnde.Name());
|
||||
Tfds.Eq("test me", xnde.Text_inner());
|
||||
}
|
||||
@Test public void Atrs() {
|
||||
xml = String_.Concat
|
||||
( "<root atr0=\"0\" atr1=\"1\">"
|
||||
, "</root>"
|
||||
);
|
||||
xdoc = XmlDoc_.parse(xml);
|
||||
XmlAtrList atrs = xdoc.Root().Atrs();
|
||||
XmlAtr atr = atrs.Get_at(1);
|
||||
tst_Atr(atr, "atr1", "1");
|
||||
atr = atrs.Get_at(1);
|
||||
tst_Atr(atr, "atr1", "1");
|
||||
}
|
||||
void tst_Atr(XmlAtr atr, String expdName, String expdVal) {
|
||||
Tfds.Eq(expdName, atr.Name());
|
||||
Tfds.Eq(expdVal, atr.Value());
|
||||
}
|
||||
}
|
||||
141
100_core/src/gplx/langs/xmls/XmlFileSplitter.java
Normal file
141
100_core/src/gplx/langs/xmls/XmlFileSplitter.java
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
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.langs.xmls; import gplx.*; import gplx.langs.*;
|
||||
import gplx.core.consoles.*;
|
||||
import gplx.core.ios.*;
|
||||
import gplx.core.texts.*;
|
||||
public class XmlFileSplitter {
|
||||
public XmlFileSplitterOpts Opts() {return opts;} XmlFileSplitterOpts opts = new XmlFileSplitterOpts();
|
||||
public byte[] Hdr() {return hdr;} private byte[] hdr;
|
||||
public void Clear() {hdr = null;}
|
||||
public void Split(Io_url xmlUrl) {
|
||||
Io_url partDir = opts.PartDir();
|
||||
byte[] xmlEndTagAry = Bry_.new_u8(opts.XmlEnd());
|
||||
byte[][] nameAry = XtoByteAry(opts.XmlNames());
|
||||
int partIdx = 0;
|
||||
|
||||
// bgn reading file
|
||||
XmlSplitRdr rdr = new XmlSplitRdr().Init_(xmlUrl, opts.FileSizeMax());
|
||||
|
||||
// split hdr: includes <root>, xmlNamespaces, and any DTD headers; will be prepended to each partFile
|
||||
rdr.Read();
|
||||
int findPos = FindMatchPos(rdr.CurAry(), nameAry); if (findPos == String_.Find_none) throw Err_.new_wo_type("could not find any names in first segment");
|
||||
byte[] dataAry = SplitHdr(rdr.CurAry(), findPos);
|
||||
if (opts.XmlBgn() != null)
|
||||
hdr = Bry_.new_u8(opts.XmlBgn());
|
||||
byte[] tempAry = new byte[0];
|
||||
int newFindPos = FindMatchPosRev(dataAry, nameAry);
|
||||
findPos = (newFindPos <= findPos) ? String_.Find_none : newFindPos;
|
||||
boolean first = true;
|
||||
|
||||
// split files
|
||||
XmlSplitWtr partWtr = new XmlSplitWtr().Init_(partDir, hdr, opts);
|
||||
while (true) {
|
||||
partWtr.Bgn(partIdx++);
|
||||
if (opts.StatusFmt() != null) Console_adp__sys.Instance.Write_str_w_nl(String_.Format(opts.StatusFmt(), partWtr.Url().NameOnly()));
|
||||
partWtr.Write(tempAry);
|
||||
if (!first) {
|
||||
rdr.Read();
|
||||
dataAry = rdr.CurAry();
|
||||
findPos = FindMatchPosRev(dataAry, nameAry);
|
||||
}
|
||||
else
|
||||
first = false;
|
||||
|
||||
// find last closing node
|
||||
while (findPos == String_.Find_none) {
|
||||
if (rdr.Done()) {
|
||||
findPos = rdr.CurRead();
|
||||
break;
|
||||
}
|
||||
else {
|
||||
partWtr.Write(dataAry);
|
||||
rdr.Read();
|
||||
dataAry = rdr.CurAry();
|
||||
findPos = FindMatchPosRev(dataAry, nameAry);
|
||||
}
|
||||
}
|
||||
|
||||
byte[][] rv = SplitRest(dataAry, findPos);
|
||||
partWtr.Write(rv[0]);
|
||||
tempAry = rv[1];
|
||||
boolean done = rdr.Done() && tempAry.length == 0;
|
||||
if (!done)
|
||||
partWtr.Write(xmlEndTagAry);
|
||||
partWtr.Rls();
|
||||
if (done) break;
|
||||
}
|
||||
rdr.Rls();
|
||||
}
|
||||
public byte[] SplitHdr(byte[] src, int findPos) {
|
||||
hdr = new byte[findPos];
|
||||
Array_.Copy_to(src, 0, hdr, 0, findPos);
|
||||
byte[] rv = new byte[src.length - findPos];
|
||||
Array_.Copy_to(src, findPos, rv, 0, rv.length);
|
||||
return rv;
|
||||
}
|
||||
public byte[][] SplitRest(byte[] src, int findPos) {
|
||||
byte[][] rv = new byte[2][];
|
||||
rv[0] = new byte[findPos];
|
||||
Array_.Copy_to(src, 0, rv[0], 0, findPos);
|
||||
rv[1] = new byte[src.length - findPos];
|
||||
Array_.Copy_to(src, findPos, rv[1], 0, rv[1].length);
|
||||
return rv;
|
||||
}
|
||||
public int FindMatchPos(byte[] src, byte[][] wordAry) {return FindMatchPos(src, wordAry, true);}
|
||||
public int FindMatchPosRev(byte[] src, byte[][] wordAry) {return FindMatchPos(src, wordAry, false);}
|
||||
int FindMatchPos(byte[] src, byte[][] wordAry, boolean fwd) {
|
||||
int[] findAry = new int[wordAry.length];
|
||||
for (int i = 0; i < findAry.length; i++)
|
||||
findAry[i] = fwd ? -1 : Int_.Max_value;
|
||||
for (int i = 0; i < wordAry.length; i++) { // look at each word in wordAry
|
||||
int srcLen = src.length, srcPos, srcEnd, srcDif;
|
||||
if (fwd) {srcPos = 0; srcEnd = srcLen; srcDif = 1;}
|
||||
else {srcPos = srcLen - 1; srcEnd = -1; srcDif = -1;}
|
||||
while (srcPos != srcEnd) { // look at each byte in src
|
||||
byte[] ary = wordAry[i];
|
||||
int aryLen = ary.length, aryPos, aryEnd, aryDif;
|
||||
if (fwd) {aryPos = 0; aryEnd = aryLen; aryDif = 1;}
|
||||
else {aryPos = aryLen - 1; aryEnd = -1; aryDif = -1;}
|
||||
boolean found = true;
|
||||
while (aryPos != aryEnd) { // look at each byte in word
|
||||
int lkpPos = srcPos + aryPos;
|
||||
if (lkpPos >= srcLen) {found = false; break;} // outside bounds; exit
|
||||
if (ary[aryPos] != src[lkpPos]) {found = false; break;} // srcByte doesn't match wordByte; exit
|
||||
aryPos += aryDif;
|
||||
}
|
||||
if (found) {findAry[i] = srcPos; break;} // result found; stop now and keep "best" result
|
||||
srcPos += srcDif;
|
||||
}
|
||||
}
|
||||
int best = fwd ? -1 : Int_.Max_value;
|
||||
for (int find : findAry) {
|
||||
if ((fwd && find > best)
|
||||
|| (!fwd && find < best))
|
||||
best = find;
|
||||
}
|
||||
if (best == Int_.Max_value) best = -1;
|
||||
return best;
|
||||
}
|
||||
byte[][] XtoByteAry(String[] names) {
|
||||
byte[][] rv = new byte[names.length][];
|
||||
for (int i = 0; i < names.length; i++)
|
||||
rv[i] = Bry_.new_u8(names[i]);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
27
100_core/src/gplx/langs/xmls/XmlFileSplitterOpts.java
Normal file
27
100_core/src/gplx/langs/xmls/XmlFileSplitterOpts.java
Normal 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.langs.xmls; import gplx.*; import gplx.langs.*;
|
||||
public class XmlFileSplitterOpts {
|
||||
public int FileSizeMax() {return fileSizeMax;} public XmlFileSplitterOpts FileSizeMax_(int v) {fileSizeMax = v; return this;} int fileSizeMax = 1024 * 1024;
|
||||
public String[] XmlNames() {return xmlNames;} public XmlFileSplitterOpts XmlNames_(String... v) {xmlNames = v; return this;} private String[] xmlNames;
|
||||
public String XmlBgn() {return xmlBgn;} public XmlFileSplitterOpts XmlBgn_(String v) {xmlBgn = v; return this;} private String xmlBgn;
|
||||
public String XmlEnd() {return xmlEnd;} public XmlFileSplitterOpts XmlEnd_(String v) {xmlEnd = v; return this;} private String xmlEnd;
|
||||
public Io_url PartDir() {return partDir;} public XmlFileSplitterOpts PartDir_(Io_url v) {partDir = v; return this;} Io_url partDir;
|
||||
public String StatusFmt() {return statusFmt;} public XmlFileSplitterOpts StatusFmt_(String v) {statusFmt = v; return this;} private String statusFmt = "splitting {0}";
|
||||
public HierStrBldr Namer() {return namer;} HierStrBldr namer = new HierStrBldr();
|
||||
}
|
||||
88
100_core/src/gplx/langs/xmls/XmlFileSplitter_tst.java
Normal file
88
100_core/src/gplx/langs/xmls/XmlFileSplitter_tst.java
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
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.langs.xmls; import gplx.*; import gplx.langs.*;
|
||||
import org.junit.*;
|
||||
import gplx.core.ios.*; import gplx.core.texts.*;
|
||||
public class XmlFileSplitter_tst {
|
||||
@Before public void setup() {
|
||||
splitter = new XmlFileSplitter();
|
||||
Io_mgr.Instance.InitEngine_mem();
|
||||
} XmlFileSplitter splitter;
|
||||
@Test public void FindMatchPos() {
|
||||
tst_FindMatchPos("abcde", "a", 0);
|
||||
tst_FindMatchPos("abcde", "b", 1);
|
||||
tst_FindMatchPos("abcde", "cd", 2);
|
||||
tst_FindMatchPos("abcde", "f", -1);
|
||||
tst_FindMatchPos("abcde", "fg", -1);
|
||||
} void tst_FindMatchPos(String src, String find, int expd) {Tfds.Eq(expd, splitter.FindMatchPos(byte_(src), byteAry_(find)));}
|
||||
@Test public void FindMatchPosRev() {
|
||||
tst_FindMatchPosRev("abcde", "a", 0);
|
||||
tst_FindMatchPosRev("abcde", "b", 1);
|
||||
tst_FindMatchPosRev("abcde", "cd", 2);
|
||||
tst_FindMatchPosRev("abcde", "f", -1);
|
||||
tst_FindMatchPosRev("abcde", "ef", -1);
|
||||
tst_FindMatchPosRev("abcde", "za", -1);
|
||||
tst_FindMatchPosRev("dbcde", "d", 3);
|
||||
} void tst_FindMatchPosRev(String src, String find, int expd) {Tfds.Eq(expd, splitter.FindMatchPosRev(byte_(src), byteAry_(find)));}
|
||||
@Test public void ExtractHdr() {
|
||||
tst_ExtractHdr("<a><b>", "<b", "<a>", "<b>");
|
||||
}
|
||||
@Test public void Split() {
|
||||
splitter.Opts().FileSizeMax_(30).XmlNames_("<a").XmlEnd_("</root>");
|
||||
tst_Split
|
||||
( "<root><a id='1'/><a id='2'/><a id='3'/><a id='4'/><a id='5'/></root>"
|
||||
, "<root><a id='1'/><a id='2'/></root>"
|
||||
, "<root><a id='3'/><a id='4'/></root>"
|
||||
, "<root><a id='5'/></root>"
|
||||
);
|
||||
tst_Split
|
||||
( "<root><a id='1' name='long_text_that_will_force_next_read'/><a id='2'/></root>"
|
||||
, "<root><a id='1' name='long_text_that_will_force_next_read'/></root>"
|
||||
, "<root><a id='2'/></root>"
|
||||
);
|
||||
}
|
||||
void tst_Split(String txt, String... expd) {
|
||||
Io_url xmlFil = Io_url_.mem_fil_("mem/800_misc/txt.xml");
|
||||
Io_url tmpDir = xmlFil.OwnerDir().GenSubDir("temp_xml");
|
||||
Io_mgr.Instance.DeleteDirDeep(tmpDir);
|
||||
splitter.Opts().StatusFmt_(null).PartDir_(tmpDir);
|
||||
splitter.Opts().Namer().Ctor_io(tmpDir, "", "fil_{0}.xml", "000");
|
||||
Io_mgr.Instance.SaveFilStr(xmlFil, txt);
|
||||
splitter.Split(xmlFil);
|
||||
Io_url[] tmpFilAry = Io_mgr.Instance.QueryDir_fils(tmpDir);
|
||||
Tfds.Eq(expd.length, tmpFilAry.length);
|
||||
for (int i = 0; i < tmpFilAry.length; i++) {
|
||||
Io_url tmpFil = tmpFilAry[i];
|
||||
Tfds.Eq(expd[i], Io_mgr.Instance.LoadFilStr(tmpFil));
|
||||
}
|
||||
}
|
||||
byte[] byte_(String s) {return Bry_.new_u8(s);}
|
||||
byte[][] byteAry_(String s) {
|
||||
byte[][] rv = new byte[1][];
|
||||
rv[0] = Bry_.new_u8(s);
|
||||
return rv;
|
||||
}
|
||||
void tst_ExtractHdr(String src, String find, String expdHdr, String expdSrc) {
|
||||
splitter.Clear();
|
||||
byte[] srcAry = byte_(src);
|
||||
int findPos = splitter.FindMatchPos(srcAry, byteAry_(find));
|
||||
srcAry = splitter.SplitHdr(srcAry, findPos);
|
||||
Tfds.Eq(String_.new_u8(splitter.Hdr()), expdHdr);
|
||||
Tfds.Eq(String_.new_u8(srcAry), expdSrc);
|
||||
}
|
||||
}
|
||||
51
100_core/src/gplx/langs/xmls/XmlNde.java
Normal file
51
100_core/src/gplx/langs/xmls/XmlNde.java
Normal 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.langs.xmls; import gplx.*; import gplx.langs.*;
|
||||
import java.io.StringWriter;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.TransformerFactoryConfigurationError;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import org.w3c.dom.Node;
|
||||
public class XmlNde {
|
||||
public XmlAtrList Atrs() {return new XmlAtrList(xnde.getAttributes());}
|
||||
public XmlNdeList SubNdes() {return new XmlNdeList_cls_xml(xnde.getChildNodes());}
|
||||
public String Name() {return xnde.getNodeName();}
|
||||
public String Xml_outer() {
|
||||
Transformer transformer = transformer_();
|
||||
StringWriter writer = new StringWriter();
|
||||
try {transformer.transform(new DOMSource(xnde), new StreamResult(writer));}
|
||||
catch (TransformerException e) {throw Err_.new_exc(e, "xml", "failed to get xml string");}
|
||||
return writer.toString();
|
||||
}
|
||||
public String Text_inner() {return xnde.getTextContent();}
|
||||
public boolean NdeType_element() {return xnde.getNodeType() == Node.ELEMENT_NODE;}
|
||||
public boolean NdeType_textOrEntityReference() {return xnde.getNodeType() == Node.TEXT_NODE || xnde.getNodeType() == Node.ENTITY_REFERENCE_NODE;}
|
||||
@gplx.Internal protected XmlNde(Node xnde) {this.xnde = xnde;} Node xnde;
|
||||
static Transformer transformer_() {
|
||||
TransformerFactory transformerfactory = TransformerFactory.newInstance();
|
||||
Transformer transformer = null;
|
||||
try {transformer = transformerfactory.newTransformer();}
|
||||
catch (TransformerConfigurationException e) {throw Err_.new_exc(e, "xml", "failed to get create transformer");}
|
||||
transformer.setOutputProperty("omit-xml-declaration", "yes");
|
||||
return transformer;
|
||||
}
|
||||
}
|
||||
35
100_core/src/gplx/langs/xmls/XmlNdeList.java
Normal file
35
100_core/src/gplx/langs/xmls/XmlNdeList.java
Normal 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.langs.xmls; import gplx.*; import gplx.langs.*;
|
||||
import org.w3c.dom.NodeList;
|
||||
public interface XmlNdeList {
|
||||
int Count();
|
||||
XmlNde Get_at(int i);
|
||||
}
|
||||
class XmlNdeList_cls_xml implements XmlNdeList {
|
||||
public int Count() {return list.getLength();}
|
||||
public XmlNde Get_at(int i) {return new XmlNde(list.item(i));}
|
||||
@gplx.Internal protected XmlNdeList_cls_xml(NodeList list) {this.list = list;} NodeList list;
|
||||
}
|
||||
class XmlNdeList_cls_list implements XmlNdeList {
|
||||
public int Count() {return list.Count();}
|
||||
public XmlNde Get_at(int i) {return (XmlNde)list.Get_at(i);}
|
||||
public void Add(XmlNde xnde) {list.Add(xnde);}
|
||||
@gplx.Internal protected XmlNdeList_cls_list(int count) {list = List_adp_.New(); list.Resize_bounds(count);} List_adp list;
|
||||
}
|
||||
//#}
|
||||
51
100_core/src/gplx/langs/xmls/XmlSplitRdr.java
Normal file
51
100_core/src/gplx/langs/xmls/XmlSplitRdr.java
Normal 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.langs.xmls; import gplx.*; import gplx.langs.*;
|
||||
import gplx.core.ios.streams.*;
|
||||
public class XmlSplitRdr {
|
||||
public byte[] CurAry() {return curAry;} private byte[] curAry;
|
||||
public long CurSum() {return curSum;} long curSum;
|
||||
public int CurRead() {return curRead;} int curRead;
|
||||
public boolean Done() {return done;} private boolean done;
|
||||
public XmlSplitRdr InitAll_(Io_url url) {
|
||||
stream = Io_mgr.Instance.OpenStreamRead(url);
|
||||
curLen = stream.Len();
|
||||
curAry = new byte[(int)curLen];
|
||||
curSum = 0;
|
||||
curRead = 0;
|
||||
done = false;
|
||||
return this;
|
||||
}
|
||||
public XmlSplitRdr Init_(Io_url url, int curArySize) {
|
||||
stream = Io_mgr.Instance.OpenStreamRead(url);
|
||||
curLen = Io_mgr.Instance.QueryFil(url).Size();
|
||||
curAry = new byte[curArySize];
|
||||
curSum = 0;
|
||||
curRead = 0;
|
||||
done = false;
|
||||
return this;
|
||||
} IoStream stream; long curLen;
|
||||
public void Read() {
|
||||
curRead = stream.ReadAry(curAry);
|
||||
curSum += curRead;
|
||||
done = curSum == curLen;
|
||||
if (done && curRead != curAry.length) // on last pass, readAry may have garbage at end, remove
|
||||
curAry = Bry_.Resize(curAry, curRead);
|
||||
}
|
||||
public void Rls() {stream.Rls();}
|
||||
}
|
||||
40
100_core/src/gplx/langs/xmls/XmlSplitWtr.java
Normal file
40
100_core/src/gplx/langs/xmls/XmlSplitWtr.java
Normal 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.langs.xmls; import gplx.*; import gplx.langs.*;
|
||||
import gplx.core.ios.streams.*;
|
||||
public class XmlSplitWtr {
|
||||
public Io_url Url() {return url;} Io_url url;
|
||||
public XmlSplitWtr Init_(Io_url partDir, byte[] hdr, XmlFileSplitterOpts opts) {
|
||||
this.partDir = partDir; this.hdr = hdr; this.opts = opts;
|
||||
return this;
|
||||
}
|
||||
public void Bgn(int partIdx) {
|
||||
String partStr = opts.Namer().GenStrIdxOnly(partIdx);
|
||||
url = Io_url_.mem_fil_(partStr);
|
||||
stream = Io_mgr.Instance.OpenStreamWrite(url);
|
||||
init = true;
|
||||
} boolean init = true; byte[] hdr; XmlFileSplitterOpts opts; Io_url partDir; IoStream stream;
|
||||
public void Write(byte[] ary) {
|
||||
if (init) {
|
||||
stream.WriteAry(hdr);
|
||||
init = false;
|
||||
}
|
||||
stream.WriteAry(ary);
|
||||
}
|
||||
public void Rls() {stream.Rls();}
|
||||
}
|
||||
106
100_core/src/gplx/langs/xmls/Xpath_.java
Normal file
106
100_core/src/gplx/langs/xmls/Xpath_.java
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
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.langs.xmls; import gplx.*; import gplx.langs.*;
|
||||
import gplx.core.primitives.*;
|
||||
public class Xpath_ {
|
||||
public static XmlNdeList SelectAll(XmlNde owner, String xpath) {return Select(owner, xpath, Xpath_Args.all_());}
|
||||
public static XmlNde SelectFirst(XmlNde owner, String xpath) {
|
||||
XmlNdeList rv = Select(owner, xpath, Xpath_Args.first_());
|
||||
return rv.Count() == 0 ? null : rv.Get_at(0); // selects first
|
||||
}
|
||||
public static XmlNdeList SelectElements(XmlNde owner) {
|
||||
XmlNdeList subNdes = owner.SubNdes(); int count = subNdes.Count();
|
||||
XmlNdeList_cls_list list = new XmlNdeList_cls_list(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
XmlNde sub = subNdes.Get_at(i);
|
||||
if (sub.NdeType_element())
|
||||
list.Add(sub);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
static XmlNdeList Select(XmlNde owner, String xpath, Xpath_Args args) {
|
||||
XmlNdeList_cls_list rv = new XmlNdeList_cls_list(8);
|
||||
String[] parts = String_.Split(xpath, "/");
|
||||
TraverseSubs(owner, parts, 0, rv, args);
|
||||
return rv;
|
||||
}
|
||||
static void TraverseSubs(XmlNde owner, String[] parts, int depth, XmlNdeList_cls_list results, Xpath_Args args) {
|
||||
int partsLen = Array_.Len(parts);
|
||||
if (depth == partsLen) return;
|
||||
String name = parts[depth];
|
||||
XmlNdeList subNdes = owner.SubNdes(); int count = subNdes.Count();
|
||||
for (int i = 0; i < count; i++) {
|
||||
XmlNde sub = subNdes.Get_at(i);
|
||||
if (args.Cancel) return;
|
||||
if (!String_.Eq(name, sub.Name())) continue;
|
||||
if (depth == partsLen - 1) {
|
||||
results.Add(sub);
|
||||
if (args.SelectFirst) args.Cancel = true;
|
||||
}
|
||||
else
|
||||
TraverseSubs(sub, parts, depth + 1, results, args);
|
||||
}
|
||||
}
|
||||
public static final String InnetTextKey = "&innerText";
|
||||
public static Keyval_hash ExtractKeyVals(String xml, Int_obj_ref posRef, String nodeName) {
|
||||
int pos = posRef.Val();
|
||||
Err xmlErr = Err_.new_wo_type("error parsing xml", "xml", xml, "pos", pos);
|
||||
String headBgnFind = "<" + nodeName + " "; int headBgnFindLen = String_.Len(headBgnFind);
|
||||
int headBgn = String_.FindFwd(xml, headBgnFind, pos); if (headBgn == String_.Find_none) return null;
|
||||
int headEnd = String_.FindFwd(xml, ">", headBgn + headBgnFindLen); if (headEnd == String_.Find_none) throw xmlErr;
|
||||
String atrXml = String_.Mid(xml, headBgn, headEnd);
|
||||
Keyval_hash rv = ExtractNodeVals(atrXml, xmlErr);
|
||||
boolean noInnerText = String_.CharAt(xml, headEnd - 1) == '/'; // if />, then no inner text
|
||||
if (!noInnerText) {
|
||||
int tail = String_.FindFwd(xml, "</" + nodeName + ">", headBgn); if (tail == String_.Find_none) throw Err_.new_wo_type("could not find tailPos", "headBgn", headBgn);
|
||||
String innerText = String_.Mid(xml, headEnd + 1, tail);
|
||||
rv.Add(InnetTextKey, innerText);
|
||||
}
|
||||
posRef.Val_(headEnd);
|
||||
return rv;
|
||||
}
|
||||
static Keyval_hash ExtractNodeVals(String xml, Err xmlErr) {
|
||||
Keyval_hash rv = new Keyval_hash();
|
||||
int pos = 0;
|
||||
while (true) {
|
||||
int eqPos = String_.FindFwd(xml, "=", pos); if (eqPos == String_.Find_none) break;
|
||||
int q0Pos = String_.FindFwd(xml, "\"", eqPos + 1); if (q0Pos == String_.Find_none) throw xmlErr.Args_add("eqPos", eqPos);
|
||||
int q1Pos = String_.FindFwd(xml, "\"", q0Pos + 1); if (q1Pos == String_.Find_none) throw xmlErr.Args_add("q1Pos", q1Pos);
|
||||
int spPos = eqPos - 1;
|
||||
while (spPos > -1) {
|
||||
char c = String_.CharAt(xml, spPos);
|
||||
if (Char_.IsWhitespace(c)) break;
|
||||
spPos--;
|
||||
}
|
||||
if (spPos == String_.Find_none) throw xmlErr.Args_add("sub_msg", "could not find hdr", "eqPos", eqPos);
|
||||
String key = String_.Mid(xml, spPos + 1, eqPos);
|
||||
String val = String_.Mid(xml, q0Pos + 1, q1Pos);
|
||||
rv.Add(key, val);
|
||||
pos = q1Pos;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
class Xpath_Args {
|
||||
public boolean SelectFirst; // false=SelectAll
|
||||
public boolean Cancel;
|
||||
public static Xpath_Args all_() {return new Xpath_Args(false);}
|
||||
public static Xpath_Args first_() {return new Xpath_Args(true);}
|
||||
Xpath_Args(boolean selectFirst) {this.SelectFirst = selectFirst;}
|
||||
}
|
||||
enum Xpath_SelectMode {All, First}
|
||||
44
100_core/src/gplx/langs/xmls/Xpath__tst.java
Normal file
44
100_core/src/gplx/langs/xmls/Xpath__tst.java
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.langs.xmls; import gplx.*; import gplx.langs.*;
|
||||
import org.junit.*;
|
||||
public class Xpath__tst {
|
||||
@Test public void Select_all() {
|
||||
String xml = String_.Concat
|
||||
( "<root>"
|
||||
, "<a>"
|
||||
, "</a>"
|
||||
, "<b>"
|
||||
, "<c/>"
|
||||
, "<c/>"
|
||||
, "<c/>"
|
||||
, "</b>"
|
||||
, "<a>"
|
||||
, "</a>"
|
||||
, "</root>"
|
||||
);
|
||||
tst_SelectAll(xml, "a", 2);
|
||||
tst_SelectAll(xml, "b", 1);
|
||||
tst_SelectAll(xml, "b/c", 3);
|
||||
}
|
||||
void tst_SelectAll(String raw, String xpath, int expdCount) {
|
||||
XmlDoc xdoc = XmlDoc_.parse(raw);
|
||||
XmlNdeList xndeList = Xpath_.SelectAll(xdoc.Root(), xpath);
|
||||
Tfds.Eq(expdCount, xndeList.Count());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user